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
90 vpath %$(C_EXT) $(SRC_DIRS)
91 vpath %$(CXX_EXT) $(SRC_DIRS)
114 ARCHIVE=$(OBJ_DIR)/lib$(PROJECT_BASE)-full$(AR_EXT)
121 # Set the object search path
123 vpath %$(OBJ_EXT) $(OBJ_DIR)
124 vpath %$(AR_EXT) $(OBJ_DIR)
126 # A target can't have a character ':' otherwise it will confuse make. We
127 # replace ':' by a pipe character. Note that there is less chance than a pipe
128 # character be part of a pathname on UNIX and this character can't be used in
129 # a pathname on Windows.
131 clean_deps = $(subst :,|,$(DEPS_PROJECTS:%=clean_%))
132 compile_deps = $(subst :,|,$(DEPS_PROJECTS:%=compile_%))
133 object_deps = $(subst :,|,$(DEPS_PROJECTS:%=object_%))
134 ada_deps = $(subst :,|,$(DEPS_PROJECTS:%=ada_%))
135 c_deps = $(subst :,|,$(DEPS_PROJECTS:%=c_%))
136 c++_deps = $(subst :,|,$(DEPS_PROJECTS:%=c++_%))
138 # Default target is to build (compile/bind/link)
141 clean: $(clean_deps) internal-clean
142 build: $(compile_deps) internal-compile internal-build
143 compile: $(compile_deps) internal-compile $(ADA_SOURCES)
144 ada: $(ada_deps) internal-ada
145 archive-objects: $(object_deps) internal-archive-objects
146 c: $(c_deps) internal-c
147 c++: $(c++deps) internal-c++
150 @$(MAKE) -C $(dir $(subst |,:,$(@:clean_%=%))) -f Makefile.$(notdir $@) internal-clean
152 $(compile_deps): force
153 @$(MAKE) -C $(dir $(subst |,:,$(@:compile_%=%))) -f Makefile.$(notdir $@) internal-compile
155 $(object_deps): force
156 @$(MAKE) -C $(dir $(subst |,:,$(@:object_%=%))) -f Makefile.$(notdir $@) internal-archive-objects ARCHIVE=$(ARCHIVE)
159 @$(MAKE) -C $(dir $(subst |,:,$(@:ada_%=%))) -f Makefile.$(notdir $@) internal-ada
162 @$(MAKE) -C $(dir $(subst |,:,$(@:c_%=%))) -f Makefile.$(notdir $@) internal-c
165 @$(MAKE) -C $(dir $(subst |,:,$(@:c++_%=%))) -f Makefile.$(notdir $@) internal-c++
171 PROJECT_BASE = $(notdir $(PROJECT_FILE))
173 # Set C/C++ linker command & target
175 ifeq ($(filter c++,$(LANGUAGES)),c++)
178 ifeq ($(filter ada,$(LANGUAGES)),ada)
180 LINKER = $(OBJ_DIR)/c++linker
181 LARGS = --LINK=$(LINKER)
183 ifeq ($(strip $(filter-out %gcc %g++,$(CXX))),)
184 # Case of GNU C++ and GNAT
186 $(LINKER): Makefile.$(PROJECT_BASE)
187 @echo \#!/bin/sh > $(LINKER)
188 @echo unset BINUTILS_ROOT >> $(LINKER)
189 @echo unset GCC_ROOT >> $(LINKER)
190 @echo $(CXX) $$\* >> $(LINKER)
194 $(LINKER): Makefile.$(PROJECT_BASE)
195 @echo \#!/bin/sh > $(LINKER)
196 @echo $(CXX) $$\* $(shell gcc -print-libgcc-file-name) >> $(LINKER)
201 ifeq ($(strip $(LANGUAGES)),c)
207 C_INCLUDES := $(foreach name,$(SRC_DIRS),-I$(name))
208 ALL_CFLAGS = $(CFLAGS) $(C_INCLUDES) $(DEP_CFLAGS)
209 ALL_CXXFLAGS = $(CXXFLAGS) $(C_INCLUDES) $(DEP_CFLAGS)
210 LDFLAGS := $(LIBS) $(LDFLAGS)
212 # Compute list of objects based on languages
214 ifeq ($(strip $(filter c,$(LANGUAGES))),c)
215 # Compute list of C sources automatically unless already specified
217 ifndef C_SRCS_DEFINED
220 $(foreach name,$(SRC_DIRS),$(notdir $(wildcard $(name)/*$(C_EXT))))
224 C_OBJECTS := $(C_SRCS:$(C_EXT)=$(OBJ_EXT))
225 OBJECTS += $(C_OBJECTS)
228 ifeq ($(strip $(filter c++,$(LANGUAGES))),c++)
229 # Compute list of C++ sources automatically unless already specified
231 ifndef CXX_SRCS_DEFINED
234 $(foreach name,$(SRC_DIRS),$(notdir $(wildcard $(name)/*$(CXX_EXT))))
238 CXX_OBJECTS := $(CXX_SRCS:$(CXX_EXT)=$(OBJ_EXT))
239 OBJECTS += $(CXX_OBJECTS)
242 OBJ_FILES := $(foreach name,$(OBJECTS),$(OBJ_DIR)/$(name))
244 # To handle C/C++ dependencies, we associate a small file for each
245 # source that will list the dependencies as a make rule, so that we can then
246 # include these rules in this makefile, and recompute them on a file by file
249 DEP_FILES := $(OBJ_FILES:$(OBJ_EXT)=.d)
251 # Ada compilations are taken care of automatically, so do not mess with Ada
252 # objects, only with main sources.
254 ifeq ($(strip $(OBJECTS)),)
256 internal-archive-objects:
259 internal-compile: lib$(PROJECT_BASE)$(AR_EXT)
261 lib$(PROJECT_BASE)$(AR_EXT): $(OBJECTS)
262 @echo creating archive file for $(PROJECT_BASE)
263 cd $(OBJ_DIR); $(AR_CMD) $@ $(strip $(OBJECTS))
264 -$(RANLIB) $(OBJ_DIR)/$@
266 internal-archive-objects: $(OBJECTS)
267 # @echo $(AR_CMD) $(ARCHIVE) $(strip $(OBJECTS))
268 # cd $(OBJ_DIR); $(AR_CMD) $(ARCHIVE) $(strip $(OBJECTS))
269 # -$(RANLIB) $(OBJ_DIR)/$@
275 # There are three cases:
279 # - Ada/C/C++, main program is in Ada
281 # - Ada/C/C++, main program is in C/C++
283 ifeq ($(strip $(filter-out c c++,$(LANGUAGES))),)
285 ifeq ($(MAIN_OBJECT),)
287 @echo link: no main object specified, exiting...
293 @echo link: no executable specified, exiting...
297 link: $(EXEC_DIR)/$(EXEC) archive-objects
298 $(EXEC_DIR)/$(EXEC): $(OBJ_FILES)
299 @echo $(LINKER) -o $(EXEC_DIR)/$(EXEC) $(OBJ_DIR)/$(MAIN_OBJECT) $(LDFLAGS)
300 $(LINKER) -o $(EXEC_DIR)/$(EXEC) $(OBJ_DIR)/$(MAIN_OBJECT) $(LDFLAGS)
304 internal-build: internal-compile link
307 ifeq ($(strip $(filter-out c c++ ada,$(LANGUAGES))),)
308 # link with Ada/C/C++
312 link: $(LINKER) archive-objects force
313 $(GNATMAKE) -b -l -P$(PROJECT_FILE) $(ADA_SOURCES) \
314 -largs $(LARGS) $(LDFLAGS)
316 internal-build: $(LINKER) archive-objects force
317 @echo $(GNATMAKE) -P$(PROJECT_FILE) $(ADA_SOURCES) $(EXEC_RULE) $(ADAFLAGS)
318 @$(GNATMAKE) -P$(PROJECT_FILE) $(EXEC_RULE) $(ADA_SOURCES) $(ADAFLAGS) \
319 -largs $(LARGS) $(LDFLAGS)
323 # The trick here is to force gnatmake to bind/link, even if there is no
324 # Ada main program. To achieve this effect, we use the -z switch, which is
325 # close enough to our needs, and the usual -n gnatbind switch and --LINK=
328 link: $(LINKER) archive-objects force
329 $(GNATMAKE) $(EXEC_RULE) -z -P$(PROJECT_FILE) $(ADA_SOURCES) \
330 -bargs -n -largs $(LARGS) $(LDFLAGS)
332 internal-build: $(LINKER) archive-objects force
333 @echo $(GNATMAKE) -z -P$(PROJECT_FILE) $(ADA_SOURCES) $(EXEC_RULE) $(ADAFLAGS)
334 @$(GNATMAKE) $(EXEC_RULE) -z \
335 -P$(PROJECT_FILE) $(ADA_SOURCES) $(ADAFLAGS) \
337 -largs $(LARGS) $(LDFLAGS)
341 # unknown set of languages, fail
343 @echo do not know how to link with the following languages: $(LANGUAGES)
348 # Automatic handling of dependencies
350 ifeq ($(strip $(filter-out %gcc %g++,$(CC) $(CXX))),)
351 # Compiler is GCC, take avantage of the preprocessor option -MD
352 DEP_CFLAGS = -Wp,-MD,$(OBJ_DIR)/$(*F).d
355 @gprcmd deps $(OBJ_EXT) $(OBJ_DIR)/$(*F).d gcc
358 # Default rule to create dummy dependency files the first time
361 @echo $(*F)$(OBJ_EXT): > $@
364 # Compiler unknown, use a more general approach based on the output of $(CC) -M
372 $(OBJ_DIR)/%.d: %$(C_EXT)
373 @$(CC) $(DEP_FLAGS) $(ALL_CFLAGS) $< > $@
374 @gprcmd deps $(OBJ_EXT) $@
376 $(OBJ_DIR)/%.d: %$(CXX_EXT)
377 @$(CXX) $(DEP_FLAGS) $(ALL_CXXFLAGS) $< > $@
378 @gprcmd deps $(OBJ_EXT) $@
381 ifneq ($(DEP_FILES),)
382 -include $(DEP_FILES)
389 # Compile C files individually
390 %$(OBJ_EXT) : %$(C_EXT)
391 @echo $(CC) -c $(CFLAGS) $< -o $(OBJ_DIR)/$@
393 @$(CC) -c $(ALL_CFLAGS) $< -o $(OBJ_DIR)/$@
397 # Compile C++ files individually
398 %$(OBJ_EXT) : %$(CXX_EXT)
399 @echo $(CXX) -c $(CXXFLAGS) $< -o $(OBJ_DIR)/$@
401 @$(CXX) -c $(ALL_CXXFLAGS) $< -o $(OBJ_DIR)/$@
405 # Compile Ada body files individually
407 $(GNATMAKE) -c -P$(PROJECT_FILE) $@ $(ADAFLAGS)
409 # Compile Ada spec files individually
411 $(GNATMAKE) -c -P$(PROJECT_FILE) $@ $(ADAFLAGS)
415 # Compile all Ada files in the project
417 $(GNATMAKE) -c -P$(PROJECT_FILE) $(ADAFLAGS)
419 # Compile all C files in the project
420 internal-c : $(C_OBJECTS)
422 # Compile all C++ files in the project
423 internal-c++ : $(CXX_OBJECTS)
425 .PHONY: force internal-clean internal-archive internal-build internal-compile internal-ada internal-c internal-c++ build compile clean ada c c++
428 @echo $(RM) $(OBJ_DIR)/*$(OBJ_EXT)
429 @$(RM) $(OBJ_DIR)/*$(OBJ_EXT)
430 @echo $(RM) $(OBJ_DIR)/*.ali
431 @$(RM) $(OBJ_DIR)/*.ali
432 @echo $(RM) $(OBJ_DIR)/b~*
433 @$(RM) $(OBJ_DIR)/b~*
434 @echo $(RM) $(OBJ_DIR)/b_*
435 @$(RM) $(OBJ_DIR)/b_*
436 @echo $(RM) $(OBJ_DIR)/*$(AR_EXT)
437 @$(RM) $(OBJ_DIR)/*$(AR_EXT)
438 @echo $(RM) $(OBJ_DIR)/*.d
439 @$(RM) $(OBJ_DIR)/*.d
441 @echo $(RM) $(EXEC_DIR)/$(EXEC)
442 @$(RM) $(EXEC_DIR)/$(EXEC)