1 # Generic Makefile to support compilation for multiple languages.
2 # See also Makefile.prolog
4 # Copyright (C) 2001-2003 ACT-Europe
6 # This Makefile provides a very generic framework of the following
9 # Multi-language support (currently any combination of Ada/C/C++ supported)
10 # Automatic handling of source dependencies
11 # Handling of various C/C++ compilers
12 # Handling of Ada sources using the GNAT toolchain
13 # Complete build process (compile/bind/link)
14 # Individual compilation (on a file, or on a language)
15 # Handling of an object directory
17 # Here are the rules that can be used from the command line:
19 # build: complete compile/bind/link process
20 # compile: compile all files that are not up-to-date
22 # ada: compile all Ada files that are not up-to-date
23 # c: ditto for C files
24 # c++: ditto for C++ files
25 # <ada file>: compile the specified file if needed.
26 # <object file>: compile the corresponding C/C++ source file if needed.
27 # clean: remove all temporary files
29 # This Makefile expects the following variables to be set by the caller
30 # (typically another Makefile):
32 # ADA_SPEC extension of Ada spec files (optional, default to .ads)
33 # ADA_BODY extension of Ada body files (optional, default to .adb)
34 # C_EXT extension of C files (optional, default to .c)
35 # CXX_EXT extension of C++ files (optional, default to .cc)
36 # OBJ_EXT extension of object files (optional, default to .o)
37 # SRC_DIRS blank separated list of source directories
38 # C_SRCS explicit list of C sources (optional)
39 # C_SRCS_DEFINED if set, indicates that C_SRCS is already set
40 # CXX_SRCS explicit list of C++ sources (optional)
41 # CXX_SRCS_DEFINED is set, indicates that CXX_SRCS is already set
42 # OBJ_DIR a single directory where object files should be put
43 # EXEC_DIR a single directory where executables should be put (optional)
44 # LANGUAGES a blank separated list of languages supported, e.g "ada c"
45 # the current list of recognized languages is: ada, c, c++
46 # CC name of the C compiler (optional, default to gcc)
47 # CXX name of the C++ compiler (optional, default to gcc)
48 # AR_CMD command to create an archive (optional, default to "ar rc")
49 # AR_EXT file extension of an archive (optional, default to ".a")
50 # RANLIB command to generate an index (optional, default to "ranlib")
51 # GNATMAKE name of the GNAT builder (optional, default to "gnatmake")
52 # ADAFLAGS additional Ada compilation switches, e.g "-gnatf" (optional)
53 # CFLAGS default C compilation switches, e.g "-O2 -g" (optional)
54 # CXXFLAGS default C++ compilation switches (optional)
55 # LIBS libraries to link with (optional)
56 # LDFLAGS linker switches (optional)
57 # ADA_SOURCES list of main Ada sources (optional)
58 # EXEC name of the final executable (optional)
59 # MAIN language of the main program (optional)
60 # MAIN_OBJECT main object file (optional)
61 # PROJECT_FILE name of the project file, without the .gpr extension
62 # DEPS_PROJECTS list of project dependencies (optional)
64 # Set the source search path for C and C++ if needed
94 vpath %$(C_EXT) $(SRC_DIRS)
95 vpath %$(CXX_EXT) $(SRC_DIRS)
118 ARCHIVE=$(OBJ_DIR)/lib$(PROJECT_BASE)-full$(AR_EXT)
125 # Set the object search path
127 vpath %$(OBJ_EXT) $(OBJ_DIR)
128 vpath %$(AR_EXT) $(OBJ_DIR)
130 # A target can't have a character ':' otherwise it will confuse make. We
131 # replace ':' by a pipe character. Note that there is less chance than a pipe
132 # character be part of a pathname on UNIX and this character can't be used in
133 # a pathname on Windows.
135 clean_deps = $(subst :,|,$(DEPS_PROJECTS:%=clean_%))
136 compile_deps = $(subst :,|,$(DEPS_PROJECTS:%=compile_%))
137 object_deps = $(subst :,|,$(DEPS_PROJECTS:%=object_%))
138 ada_deps = $(subst :,|,$(DEPS_PROJECTS:%=ada_%))
139 c_deps = $(subst :,|,$(DEPS_PROJECTS:%=c_%))
140 c++_deps = $(subst :,|,$(DEPS_PROJECTS:%=c++_%))
142 # Default target is to build (compile/bind/link)
145 clean: $(clean_deps) internal-clean
146 build: $(compile_deps) internal-compile internal-build
147 compile: $(compile_deps) internal-compile $(ADA_SOURCES)
148 ada: $(ada_deps) internal-ada
149 archive-objects: $(object_deps) internal-archive-objects
150 c: $(c_deps) internal-c
151 c++: $(c++deps) internal-c++
154 @$(MAKE) -C $(dir $(subst |,:,$(@:clean_%=%))) -f Makefile.$(notdir $@) internal-clean
156 $(compile_deps): force
157 @$(MAKE) -C $(dir $(subst |,:,$(@:compile_%=%))) -f Makefile.$(notdir $@) internal-compile
159 $(object_deps): force
160 @$(MAKE) -C $(dir $(subst |,:,$(@:object_%=%))) -f Makefile.$(notdir $@) internal-archive-objects ARCHIVE=$(ARCHIVE)
163 @$(MAKE) -C $(dir $(subst |,:,$(@:ada_%=%))) -f Makefile.$(notdir $@) internal-ada
166 @$(MAKE) -C $(dir $(subst |,:,$(@:c_%=%))) -f Makefile.$(notdir $@) internal-c
169 @$(MAKE) -C $(dir $(subst |,:,$(@:c++_%=%))) -f Makefile.$(notdir $@) internal-c++
175 PROJECT_BASE = $(notdir $(PROJECT_FILE))
177 # Set C/C++ linker command & target
179 ifeq ($(filter c++,$(LANGUAGES)),c++)
182 ifeq ($(filter ada,$(LANGUAGES)),ada)
184 LINKER = $(OBJ_DIR)/c++linker
185 LARGS = --LINK=$(LINKER)
187 ifeq ($(strip $(filter-out %gcc %g++,$(CXX))),)
188 # Case of GNU C++ and GNAT
190 $(LINKER): Makefile.$(PROJECT_BASE)
191 @echo \#!/bin/sh > $(LINKER)
192 @echo unset BINUTILS_ROOT >> $(LINKER)
193 @echo unset GCC_ROOT >> $(LINKER)
194 @echo $(CXX) $$\* >> $(LINKER)
198 $(LINKER): Makefile.$(PROJECT_BASE)
199 @echo \#!/bin/sh > $(LINKER)
200 @echo $(CXX) $$\* $(shell gcc -print-libgcc-file-name) >> $(LINKER)
205 ifeq ($(strip $(LANGUAGES)),c)
211 C_INCLUDES := $(foreach name,$(SRC_DIRS),-I$(name))
212 ALL_CFLAGS = $(CFLAGS) $(C_INCLUDES) $(DEP_CFLAGS)
213 ALL_CXXFLAGS = $(CXXFLAGS) $(C_INCLUDES) $(DEP_CFLAGS)
214 LDFLAGS := $(LIBS) $(LDFLAGS)
216 # Compute list of objects based on languages
218 ifeq ($(strip $(filter c,$(LANGUAGES))),c)
219 # Compute list of C sources automatically unless already specified
221 ifndef C_SRCS_DEFINED
224 $(foreach name,$(SRC_DIRS),$(notdir $(wildcard $(name)/*$(C_EXT))))
228 C_OBJECTS := $(C_SRCS:$(C_EXT)=$(OBJ_EXT))
229 OBJECTS += $(C_OBJECTS)
232 ifeq ($(strip $(filter c++,$(LANGUAGES))),c++)
233 # Compute list of C++ sources automatically unless already specified
235 ifndef CXX_SRCS_DEFINED
238 $(foreach name,$(SRC_DIRS),$(notdir $(wildcard $(name)/*$(CXX_EXT))))
242 CXX_OBJECTS := $(CXX_SRCS:$(CXX_EXT)=$(OBJ_EXT))
243 OBJECTS += $(CXX_OBJECTS)
246 OBJ_FILES := $(foreach name,$(OBJECTS),$(OBJ_DIR)/$(name))
248 # To handle C/C++ dependencies, we associate a small file for each
249 # source that will list the dependencies as a make rule, so that we can then
250 # include these rules in this makefile, and recompute them on a file by file
253 DEP_FILES := $(OBJ_FILES:$(OBJ_EXT)=.d)
255 # Ada compilations are taken care of automatically, so do not mess with Ada
256 # objects, only with main sources.
258 ifeq ($(strip $(OBJECTS)),)
260 internal-archive-objects:
263 internal-compile: lib$(PROJECT_BASE)$(AR_EXT)
265 lib$(PROJECT_BASE)$(AR_EXT): $(OBJECTS)
266 @echo creating archive file for $(PROJECT_BASE)
267 cd $(OBJ_DIR); $(AR_CMD) $@ $(strip $(OBJECTS))
268 -$(RANLIB) $(OBJ_DIR)/$@
270 internal-archive-objects: $(OBJECTS)
271 # @echo $(AR_CMD) $(ARCHIVE) $(strip $(OBJECTS))
272 # cd $(OBJ_DIR); $(AR_CMD) $(ARCHIVE) $(strip $(OBJECTS))
273 # -$(RANLIB) $(OBJ_DIR)/$@
279 # There are three cases:
283 # - Ada/C/C++, main program is in Ada
285 # - Ada/C/C++, main program is in C/C++
287 ifeq ($(strip $(filter-out c c++,$(LANGUAGES))),)
289 ifeq ($(MAIN_OBJECT),)
291 @echo link: no main object specified, exiting...
297 @echo link: no executable specified, exiting...
301 link: $(EXEC_DIR)/$(EXEC) archive-objects
302 $(EXEC_DIR)/$(EXEC): $(OBJ_FILES)
303 @echo $(LINKER) -o $(EXEC_DIR)/$(EXEC) $(OBJ_DIR)/$(MAIN_OBJECT) $(LDFLAGS)
304 $(LINKER) -o $(EXEC_DIR)/$(EXEC) $(OBJ_DIR)/$(MAIN_OBJECT) $(LDFLAGS)
308 internal-build: internal-compile link
311 ifeq ($(strip $(filter-out c c++ ada,$(LANGUAGES))),)
312 # link with Ada/C/C++
316 link: $(LINKER) archive-objects force
317 $(GNATMAKE) -b -l -P$(PROJECT_FILE) $(ADA_SOURCES) \
318 -largs $(LARGS) $(LDFLAGS)
320 internal-build: $(LINKER) archive-objects force
321 @echo $(GNATMAKE) -P$(PROJECT_FILE) $(ADA_SOURCES) $(EXEC_RULE) $(ADAFLAGS)
322 @$(GNATMAKE) -P$(PROJECT_FILE) $(EXEC_RULE) $(ADA_SOURCES) $(ADAFLAGS) \
323 -largs $(LARGS) $(LDFLAGS)
327 # The trick here is to force gnatmake to bind/link, even if there is no
328 # Ada main program. To achieve this effect, we use the -z switch, which is
329 # close enough to our needs, and the usual -n gnatbind switch and --LINK=
332 link: $(LINKER) archive-objects force
333 $(GNATMAKE) $(EXEC_RULE) -z -P$(PROJECT_FILE) $(ADA_SOURCES) \
334 -bargs -n -largs $(LARGS) $(LDFLAGS)
336 internal-build: $(LINKER) archive-objects force
337 @echo $(GNATMAKE) -z -P$(PROJECT_FILE) $(ADA_SOURCES) $(EXEC_RULE) $(ADAFLAGS)
338 @$(GNATMAKE) $(EXEC_RULE) -z \
339 -P$(PROJECT_FILE) $(ADA_SOURCES) $(ADAFLAGS) \
341 -largs $(LARGS) $(LDFLAGS)
345 # unknown set of languages, fail
347 @echo do not know how to link with the following languages: $(LANGUAGES)
352 # Automatic handling of dependencies
354 ifeq ($(strip $(filter-out %gcc %g++,$(CC) $(CXX))),)
355 # Compiler is GCC, take avantage of the preprocessor option -MD
356 DEP_CFLAGS = -Wp,-MD,$(OBJ_DIR)/$(*F).d
359 @gprcmd deps $(OBJ_EXT) $(OBJ_DIR)/$(*F).d gcc
362 # Default rule to create dummy dependency files the first time
365 @echo $(*F)$(OBJ_EXT): > $@
368 # Compiler unknown, use a more general approach based on the output of $(CC) -M
376 $(OBJ_DIR)/%.d: %$(C_EXT)
377 @$(CC) $(DEP_FLAGS) $(ALL_CFLAGS) $< > $@
378 @gprcmd deps $(OBJ_EXT) $@
380 $(OBJ_DIR)/%.d: %$(CXX_EXT)
381 @$(CXX) $(DEP_FLAGS) $(ALL_CXXFLAGS) $< > $@
382 @gprcmd deps $(OBJ_EXT) $@
385 ifneq ($(DEP_FILES),)
386 -include $(DEP_FILES)
393 # Compile C files individually
394 %$(OBJ_EXT) : %$(C_EXT)
395 @echo $(CC) -c $(CFLAGS) $< -o $(OBJ_DIR)/$@
397 @$(CC) -c $(ALL_CFLAGS) $< -o $(OBJ_DIR)/$@
401 # Compile C++ files individually
402 %$(OBJ_EXT) : %$(CXX_EXT)
403 @echo $(CXX) -c $(CXXFLAGS) $< -o $(OBJ_DIR)/$@
405 @$(CXX) -c $(ALL_CXXFLAGS) $< -o $(OBJ_DIR)/$@
409 # Compile Ada body files individually
411 $(GNATMAKE) -c -P$(PROJECT_FILE) $@ $(ADAFLAGS)
413 # Compile Ada spec files individually
415 $(GNATMAKE) -c -P$(PROJECT_FILE) $@ $(ADAFLAGS)
419 # Compile all Ada files in the project
421 $(GNATMAKE) -c -P$(PROJECT_FILE) $(ADAFLAGS)
423 # Compile all C files in the project
424 internal-c : $(C_OBJECTS)
426 # Compile all C++ files in the project
427 internal-c++ : $(CXX_OBJECTS)
429 .PHONY: force internal-clean internal-archive internal-build internal-compile internal-ada internal-c internal-c++ build compile clean ada c c++
432 @echo $(RM) $(OBJ_DIR)/*$(OBJ_EXT)
433 @$(RM) $(OBJ_DIR)/*$(OBJ_EXT)
434 @echo $(RM) $(OBJ_DIR)/*.ali
435 @$(RM) $(OBJ_DIR)/*.ali
436 @echo $(RM) $(OBJ_DIR)/b~*
437 @$(RM) $(OBJ_DIR)/b~*
438 @echo $(RM) $(OBJ_DIR)/b_*
439 @$(RM) $(OBJ_DIR)/b_*
440 @echo $(RM) $(OBJ_DIR)/*$(AR_EXT)
441 @$(RM) $(OBJ_DIR)/*$(AR_EXT)
442 @echo $(RM) $(OBJ_DIR)/*.d
443 @$(RM) $(OBJ_DIR)/*.d
445 @echo $(RM) $(EXEC_DIR)/$(EXEC)
446 @$(RM) $(EXEC_DIR)/$(EXEC)