| # Generic Makefile to support compilation for multiple languages. |
| # See also Makefile.prolog |
| # |
| # Copyright (C) 2001-2004 Free Software Foundation, Inc. |
| |
| # This file is part of GCC. |
| |
| # GCC is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2, or (at your option) |
| # any later version. |
| |
| # GCC is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| |
| # You should have received a copy of the GNU General Public License |
| # along with GCC; see the file COPYING. If not, write to |
| # the Free Software Foundation, 59 Temple Place - Suite 330, |
| # Boston, MA 02111-1307, USA. |
| |
| # This Makefile provides a very generic framework of the following |
| # functionalities: |
| # |
| # Multi-language support (currently any combination of Ada/C/C++ supported) |
| # Automatic handling of source dependencies |
| # Handling of various C/C++ compilers |
| # Handling of Ada sources using the GNAT toolchain |
| # Complete build process (compile/bind/link) |
| # Individual compilation (on a file, or on a language) |
| # Handling of an object directory |
| |
| # Here are the rules that can be used from the command line: |
| # |
| # build: complete compile/bind/link process |
| # compile: compile all files that are not up-to-date |
| # link: bind/link |
| # ada: compile all Ada files that are not up-to-date |
| # c: ditto for C files |
| # c++: ditto for C++ files |
| # <ada file>: compile the specified file if needed. |
| # <object file>: compile the corresponding C/C++ source file if needed. |
| # clean: remove all temporary files |
| |
| # This Makefile expects the following variables to be set by the caller |
| # (typically another Makefile): |
| # |
| # ADA_SPEC extension of Ada spec files (optional, default to .ads) |
| # ADA_BODY extension of Ada body files (optional, default to .adb) |
| # C_EXT extension of C files (optional, default to .c) |
| # CXX_EXT extension of C++ files (optional, default to .cc) |
| # OBJ_EXT extension of object files (optional, default to .o) |
| # SRC_DIRS blank separated list of source directories |
| # C_SRCS explicit list of C sources (optional) |
| # C_SRCS_DEFINED if set, indicates that C_SRCS is already set |
| # CXX_SRCS explicit list of C++ sources (optional) |
| # CXX_SRCS_DEFINED is set, indicates that CXX_SRCS is already set |
| # OBJ_DIR a single directory where object files should be put |
| # EXEC_DIR a single directory where executables should be put (optional) |
| # LANGUAGES a blank separated list of languages supported, e.g "ada c" |
| # the current list of recognized languages is: ada, c, c++ |
| # CC name of the C compiler (optional, default to gcc) |
| # CXX name of the C++ compiler (optional, default to gcc) |
| # AR_CMD command to create an archive (optional, default to "ar rc") |
| # AR_EXT file extension of an archive (optional, default to ".a") |
| # RANLIB command to generate an index (optional, default to "ranlib") |
| # GNATMAKE name of the GNAT builder (optional, default to "gnatmake") |
| # ADAFLAGS additional Ada compilation switches, e.g "-gnatf" (optional) |
| # CFLAGS default C compilation switches, e.g "-O2 -g" (optional) |
| # CXXFLAGS default C++ compilation switches (optional) |
| # LIBS libraries to link with (optional) |
| # LDFLAGS linker switches (optional) |
| # ADA_SOURCES list of main Ada sources (optional) |
| # EXEC name of the final executable (optional) |
| # MAIN language of the main program (optional) |
| # MAIN_OBJECT main object file (optional) |
| # PROJECT_FILE name of the project file, without the .gpr extension |
| # DEPS_PROJECTS list of project dependencies (optional) |
| |
| # Set the source search path for C and C++ if needed |
| |
| ifndef MAIN |
| MAIN=ada |
| endif |
| |
| ifndef ADA_SPEC |
| ADA_SPEC=.ads |
| endif |
| |
| ifndef ADA_BODY |
| ADA_BODY=.adb |
| endif |
| |
| ifndef CC |
| CC=gcc |
| endif |
| |
| ifndef CXX |
| CXX=gcc |
| endif |
| |
| ifndef CXX_EXT |
| CXX_EXT=.cc |
| endif |
| |
| vpath %$(C_EXT) $(SRC_DIRS) |
| vpath %$(CXX_EXT) $(SRC_DIRS) |
| |
| ifndef OBJ_EXT |
| OBJ_EXT=.o |
| endif |
| |
| ifndef AR_EXT |
| AR_EXT=.a |
| endif |
| |
| ifndef AR_CMD |
| AR_CMD=ar rc |
| endif |
| |
| ifndef RANLIB |
| RANLIB=ranlib |
| endif |
| |
| ifndef GNATMAKE |
| GNATMAKE=gnatmake |
| endif |
| |
| ifndef ARCHIVE |
| ARCHIVE=$(OBJ_DIR)/lib$(PROJECT_BASE)-full$(AR_EXT) |
| endif |
| |
| ifeq ($(EXEC_DIR),) |
| EXEC_DIR=$(OBJ_DIR) |
| endif |
| |
| # Set the object search path |
| |
| vpath %$(OBJ_EXT) $(OBJ_DIR) |
| vpath %$(AR_EXT) $(OBJ_DIR) |
| |
| # A target can't have a character ':' otherwise it will confuse make. We |
| # replace ':' by a pipe character. Note that there is less chance than a pipe |
| # character be part of a pathname on UNIX and this character can't be used in |
| # a pathname on Windows. |
| |
| clean_deps = $(subst :,|,$(DEPS_PROJECTS:%=clean_%)) |
| compile_deps = $(subst :,|,$(DEPS_PROJECTS:%=compile_%)) |
| object_deps = $(subst :,|,$(DEPS_PROJECTS:%=object_%)) |
| ada_deps = $(subst :,|,$(DEPS_PROJECTS:%=ada_%)) |
| c_deps = $(subst :,|,$(DEPS_PROJECTS:%=c_%)) |
| c++_deps = $(subst :,|,$(DEPS_PROJECTS:%=c++_%)) |
| |
| # Default target is to build (compile/bind/link) |
| all: build |
| |
| clean: $(clean_deps) internal-clean |
| build: $(compile_deps) internal-compile internal-build |
| compile: $(compile_deps) internal-compile $(ADA_SOURCES) |
| ada: $(ada_deps) internal-ada |
| archive-objects: $(object_deps) internal-archive-objects |
| c: $(c_deps) internal-c |
| c++: $(c++deps) internal-c++ |
| |
| $(clean_deps): force |
| @$(MAKE) -C $(dir $(subst |,:,$(@:clean_%=%))) -f Makefile.$(notdir $@) internal-clean |
| |
| $(compile_deps): force |
| @$(MAKE) -C $(dir $(subst |,:,$(@:compile_%=%))) -f Makefile.$(notdir $@) internal-compile |
| |
| $(object_deps): force |
| @$(MAKE) -C $(dir $(subst |,:,$(@:object_%=%))) -f Makefile.$(notdir $@) internal-archive-objects ARCHIVE=$(ARCHIVE) |
| |
| $(ada_deps): force |
| @$(MAKE) -C $(dir $(subst |,:,$(@:ada_%=%))) -f Makefile.$(notdir $@) internal-ada |
| |
| $(c_deps): force |
| @$(MAKE) -C $(dir $(subst |,:,$(@:c_%=%))) -f Makefile.$(notdir $@) internal-c |
| |
| $(c++_deps): force |
| @$(MAKE) -C $(dir $(subst |,:,$(@:c++_%=%))) -f Makefile.$(notdir $@) internal-c++ |
| |
| ifneq ($(EXEC),) |
| EXEC_RULE=-o $(EXEC) |
| endif |
| |
| PROJECT_BASE = $(notdir $(PROJECT_FILE)) |
| |
| # Set C/C++ linker command & target |
| |
| ifeq ($(filter c++,$(LANGUAGES)),c++) |
| LINKER = $(CXX) |
| |
| ifeq ($(filter ada,$(LANGUAGES)),ada) |
| # C++ and Ada mixed |
| LINKER = $(OBJ_DIR)/c++linker |
| LARGS = --LINK=$(LINKER) |
| |
| ifeq ($(strip $(filter-out %gcc %g++,$(CXX))),) |
| # Case of GNU C++ and GNAT |
| |
| $(LINKER): Makefile.$(PROJECT_BASE) |
| @echo \#!/bin/sh > $(LINKER) |
| @echo unset BINUTILS_ROOT >> $(LINKER) |
| @echo unset GCC_ROOT >> $(LINKER) |
| @echo $(CXX) $$\* >> $(LINKER) |
| @chmod +x $(LINKER) |
| |
| else |
| $(LINKER): Makefile.$(PROJECT_BASE) |
| @echo \#!/bin/sh > $(LINKER) |
| @echo $(CXX) $$\* $(shell gcc -print-libgcc-file-name) >> $(LINKER) |
| @chmod +x $(LINKER) |
| endif |
| endif |
| else |
| ifeq ($(strip $(LANGUAGES)),c) |
| # Case of C only |
| LINKER = $(CC) |
| endif |
| endif |
| |
| C_INCLUDES := $(foreach name,$(SRC_DIRS),-I$(name)) |
| ALL_CFLAGS = $(CFLAGS) $(C_INCLUDES) $(DEP_CFLAGS) |
| ALL_CXXFLAGS = $(CXXFLAGS) $(C_INCLUDES) $(DEP_CFLAGS) |
| LDFLAGS := $(LIBS) $(LDFLAGS) |
| |
| # Compute list of objects based on languages |
| |
| ifeq ($(strip $(filter c,$(LANGUAGES))),c) |
| # Compute list of C sources automatically unless already specified |
| |
| ifndef C_SRCS_DEFINED |
| ifndef C_SRCS |
| C_SRCS := \ |
| $(foreach name,$(SRC_DIRS),$(notdir $(wildcard $(name)/*$(C_EXT)))) |
| endif |
| endif |
| |
| C_OBJECTS := $(C_SRCS:$(C_EXT)=$(OBJ_EXT)) |
| OBJECTS += $(C_OBJECTS) |
| endif |
| |
| ifeq ($(strip $(filter c++,$(LANGUAGES))),c++) |
| # Compute list of C++ sources automatically unless already specified |
| |
| ifndef CXX_SRCS_DEFINED |
| ifndef CXX_SRCS |
| CXX_SRCS := \ |
| $(foreach name,$(SRC_DIRS),$(notdir $(wildcard $(name)/*$(CXX_EXT)))) |
| endif |
| endif |
| |
| CXX_OBJECTS := $(CXX_SRCS:$(CXX_EXT)=$(OBJ_EXT)) |
| OBJECTS += $(CXX_OBJECTS) |
| endif |
| |
| OBJ_FILES := $(foreach name,$(OBJECTS),$(OBJ_DIR)/$(name)) |
| |
| # To handle C/C++ dependencies, we associate a small file for each |
| # source that will list the dependencies as a make rule, so that we can then |
| # include these rules in this makefile, and recompute them on a file by file |
| # basis |
| |
| DEP_FILES := $(OBJ_FILES:$(OBJ_EXT)=.d) |
| |
| # Ada compilations are taken care of automatically, so do not mess with Ada |
| # objects, only with main sources. |
| |
| ifeq ($(strip $(OBJECTS)),) |
| internal-compile: |
| internal-archive-objects: |
| |
| else |
| internal-compile: lib$(PROJECT_BASE)$(AR_EXT) |
| |
| lib$(PROJECT_BASE)$(AR_EXT): $(OBJECTS) |
| @echo creating archive file for $(PROJECT_BASE) |
| cd $(OBJ_DIR); $(AR_CMD) $@ $(strip $(OBJECTS)) |
| -$(RANLIB) $(OBJ_DIR)/$@ |
| |
| internal-archive-objects: $(OBJECTS) |
| # @echo $(AR_CMD) $(ARCHIVE) $(strip $(OBJECTS)) |
| # cd $(OBJ_DIR); $(AR_CMD) $(ARCHIVE) $(strip $(OBJECTS)) |
| # -$(RANLIB) $(OBJ_DIR)/$@ |
| |
| endif |
| |
| # Linking rules |
| |
| # There are three cases: |
| # |
| # - C/C++ sources |
| # |
| # - Ada/C/C++, main program is in Ada |
| # |
| # - Ada/C/C++, main program is in C/C++ |
| |
| ifeq ($(strip $(filter-out c c++,$(LANGUAGES))),) |
| # link with C/C++ |
| ifeq ($(MAIN_OBJECT),) |
| link: |
| @echo link: no main object specified, exiting... |
| exit 1 |
| else |
| ifeq ($(EXEC),) |
| |
| link: |
| @echo link: no executable specified, exiting... |
| exit 1 |
| else |
| |
| link: $(EXEC_DIR)/$(EXEC) archive-objects |
| $(EXEC_DIR)/$(EXEC): $(OBJ_FILES) |
| @echo $(LINKER) -o $(EXEC_DIR)/$(EXEC) $(OBJ_DIR)/$(MAIN_OBJECT) $(LDFLAGS) |
| $(LINKER) -o $(EXEC_DIR)/$(EXEC) $(OBJ_DIR)/$(MAIN_OBJECT) $(LDFLAGS) |
| endif |
| endif |
| |
| internal-build: internal-compile link |
| |
| else |
| ifeq ($(strip $(filter-out c c++ ada,$(LANGUAGES))),) |
| # link with Ada/C/C++ |
| |
| ifeq ($(MAIN),ada) |
| # Ada main |
| link: $(LINKER) archive-objects force |
| $(GNATMAKE) -b -l -P$(PROJECT_FILE) $(ADA_SOURCES) \ |
| -largs $(LARGS) $(LDFLAGS) |
| |
| internal-build: $(LINKER) archive-objects force |
| @echo $(GNATMAKE) -P$(PROJECT_FILE) $(ADA_SOURCES) $(EXEC_RULE) $(ADAFLAGS) |
| @$(GNATMAKE) -P$(PROJECT_FILE) $(EXEC_RULE) $(ADA_SOURCES) $(ADAFLAGS) \ |
| -largs $(LARGS) $(LDFLAGS) |
| |
| else |
| # C/C++ main |
| # The trick here is to force gnatmake to bind/link, even if there is no |
| # Ada main program. To achieve this effect, we use the -z switch, which is |
| # close enough to our needs, and the usual -n gnatbind switch and --LINK= |
| # gnatlink switch. |
| |
| link: $(LINKER) archive-objects force |
| $(GNATMAKE) $(EXEC_RULE) -z -P$(PROJECT_FILE) $(ADA_SOURCES) \ |
| -bargs -n -largs $(LARGS) $(LDFLAGS) |
| |
| internal-build: $(LINKER) archive-objects force |
| @echo $(GNATMAKE) -z -P$(PROJECT_FILE) $(ADA_SOURCES) $(EXEC_RULE) $(ADAFLAGS) |
| @$(GNATMAKE) $(EXEC_RULE) -z \ |
| -P$(PROJECT_FILE) $(ADA_SOURCES) $(ADAFLAGS) \ |
| -bargs -n \ |
| -largs $(LARGS) $(LDFLAGS) |
| endif |
| |
| else |
| # unknown set of languages, fail |
| link: |
| @echo do not know how to link with the following languages: $(LANGUAGES) |
| exit 1 |
| endif |
| endif |
| |
| # Automatic handling of dependencies |
| |
| ifeq ($(strip $(filter-out %gcc %g++,$(CC) $(CXX))),) |
| # Compiler is GCC, take avantage of the preprocessor option -MD |
| DEP_CFLAGS = -Wp,-MD,$(OBJ_DIR)/$(*F).d |
| |
| define post-compile |
| @gprcmd deps $(OBJ_EXT) $(OBJ_DIR)/$(*F).d gcc |
| endef |
| |
| # Default rule to create dummy dependency files the first time |
| |
| $(OBJ_DIR)/%.d: |
| @echo $(*F)$(OBJ_EXT): > $@ |
| |
| else |
| # Compiler unknown, use a more general approach based on the output of $(CC) -M |
| |
| DEP_FLAGS = -M |
| DEP_CFLAGS = |
| |
| define post-compile |
| endef |
| |
| $(OBJ_DIR)/%.d: %$(C_EXT) |
| @$(CC) $(DEP_FLAGS) $(ALL_CFLAGS) $< > $@ |
| @gprcmd deps $(OBJ_EXT) $@ |
| |
| $(OBJ_DIR)/%.d: %$(CXX_EXT) |
| @$(CXX) $(DEP_FLAGS) $(ALL_CXXFLAGS) $< > $@ |
| @gprcmd deps $(OBJ_EXT) $@ |
| endif |
| |
| ifneq ($(DEP_FILES),) |
| -include $(DEP_FILES) |
| endif |
| |
| # Compilation rules |
| |
| # File rules |
| |
| # Compile C files individually |
| %$(OBJ_EXT) : %$(C_EXT) |
| @echo $(CC) -c $(CFLAGS) $< -o $(OBJ_DIR)/$@ |
| ifndef FAKE_COMPILE |
| @$(CC) -c $(ALL_CFLAGS) $< -o $(OBJ_DIR)/$@ |
| @$(post-compile) |
| endif |
| |
| # Compile C++ files individually |
| %$(OBJ_EXT) : %$(CXX_EXT) |
| @echo $(CXX) -c $(CXXFLAGS) $< -o $(OBJ_DIR)/$@ |
| ifndef FAKE_COMPILE |
| @$(CXX) -c $(ALL_CXXFLAGS) $< -o $(OBJ_DIR)/$@ |
| @$(post-compile) |
| endif |
| |
| # Compile Ada body files individually |
| %$(ADA_BODY) : force |
| $(GNATMAKE) -c -P$(PROJECT_FILE) $@ $(ADAFLAGS) |
| |
| # Compile Ada spec files individually |
| %$(ADA_SPEC) : force |
| $(GNATMAKE) -c -P$(PROJECT_FILE) $@ $(ADAFLAGS) |
| |
| # Languages rules |
| |
| # Compile all Ada files in the project |
| internal-ada : |
| $(GNATMAKE) -c -P$(PROJECT_FILE) $(ADAFLAGS) |
| |
| # Compile all C files in the project |
| internal-c : $(C_OBJECTS) |
| |
| # Compile all C++ files in the project |
| internal-c++ : $(CXX_OBJECTS) |
| |
| .PHONY: force internal-clean internal-archive internal-build internal-compile internal-ada internal-c internal-c++ build compile clean ada c c++ |
| |
| internal-clean: |
| @echo $(RM) $(OBJ_DIR)/*$(OBJ_EXT) |
| @$(RM) $(OBJ_DIR)/*$(OBJ_EXT) |
| @echo $(RM) $(OBJ_DIR)/*.ali |
| @$(RM) $(OBJ_DIR)/*.ali |
| @echo $(RM) $(OBJ_DIR)/b~* |
| @$(RM) $(OBJ_DIR)/b~* |
| @echo $(RM) $(OBJ_DIR)/b_* |
| @$(RM) $(OBJ_DIR)/b_* |
| @echo $(RM) $(OBJ_DIR)/*$(AR_EXT) |
| @$(RM) $(OBJ_DIR)/*$(AR_EXT) |
| @echo $(RM) $(OBJ_DIR)/*.d |
| @$(RM) $(OBJ_DIR)/*.d |
| ifneq ($(EXEC),) |
| @echo $(RM) $(EXEC_DIR)/$(EXEC) |
| @$(RM) $(EXEC_DIR)/$(EXEC) |
| endif |
| |
| force: |
| |