Here we include a complete copy of
rules/object-code/ccxx.mk.
# This makefile rules fragment supports compilation of C and C++ code
# into static libraries and dynamically linked executables. Shared
# libraries are not presently supported but will be in the future.
# Please see the file make/README.shared-libraries for details.
#
# Please see ccxx-help.txt for details on how to use these rules.
# ---------------
# Notes to implementors
# CCXX_TOOLCHAIN contains the name of a makefile fragment (without the
# .mk; loaded from abuild-specified search path) that defines the
# functions that these rules use to perform actual compiles. The best
# place to learn about how these work, in addition to carefully
# reading these notes, is to look at the built-in compiler support
# files included with abuild. gcc.mk is a good UNIX example, and
# msvc.mk is a good Windows example. The compiler support file
# provide the following:
# .LIBPATTERNS: gnu make variable which must contain patterns to
# match library names so that dependencies on -llib will work.
# OBJ: the suffix of non-library object files
# LOBJ: the suffix of library object files; may be the same as OBJ
# PREPROCESS_c: a command used to invoke the C preprocessor
# PREPROCESS_cxx: a command used to invoke the C++ preprocessor
# COMPILE_c: a command used to invoke the C compiler
# COMPILE_cxx: a command used to invoke the C++ compiler
# LINK_c: a command used to invoke the linker for a C program that
# uses no C++ libraries
# LINK_cxx: a command used to invoke the linker for a C++ program
# DFLAGS: default debugging flags
# OFLAGS: default optimization flags
# WFLAGS: default warning flags
# CCXX_GEN_DEPS: if it is possible to make COMPILE_c and COMPILE_cxx
# generate correct dependency information as a side effect of
# compilation, add the appropriate flags to COMPILE_c and
# COMPILE_cxx and set CCXX_GEN_DEPS to @: to suppress the running of
# gen_deps. Otherwise, don't set this variable, in which case it
# will default to $(GEN_DEPS). Abuild requires dependency files
# that contain an empty rule with each object file depending on all
# of its dependencies as well as an empty rule for each dependency
# that depends on nothing. This way, missing header files will
# cause the target to rebuild instead of fail. Our own gen_deps
# does this, as does gcc's -MP option.
# IGNORE_TARGETS: optional: a list of targets (object files,
# libraries, etc.) that should be ignored when determining whether
# there are orphan targets.
# $(call libname,libbase): a function that returns the full name of
# a library from its base. For example, $(call libname,moo) would
# typically return libmoo.a on a UNIX system and moo.lib on a
# Windows system.
# $(call shlibname,libbase,major,minor,revision): a function that
# returns the full name of a shared library from its base, major
# version, minor version, and revision number. For example, $(call
# shlibname,moo,1,2,3) might return libmoo.so.1.2.3 on a UNIX system
# and moo1.dll on a Windows system. The version arguments are
# optional. Each one must be ignored if the ones before it are
# omitted.
# $(call binname,binbase): a function that returns the full name of
# an executable from its base. For example, $(call binname,moo)
# would typically return moo on a UNIX system and moo.exe on a
# Windows system.
# $(call include_flags,include-dirs): a function that returns
# include flags forthe given include directories. This result
# should be suitable to passing as flags to the preprocessor and C
# or C++ compiler.
# $(call make_obj,compiler,pic,flags,src,obj): a function that uses
# the given compiler to convert src to obj. The first argument will
# always be either $(COMPILE_c) or $(COMPILE_cxx). The second
# argument will be 1 if we need position-independent code for shared
# libraries (or static libraries that might be linked into shared
# libraries) and empty otherwise.
# $(call make_lib,objects,libbase): a function that creates a
# library with the given base name. Note that libbase has not been
# passed to $(libname).
# $(call make_bin,linker,compiler-flags,link-flags,objects,lib-dirs,li\
\bs,binbase):
# a function that generates an executable file with the given base
# name from the given objects linking from libs that are found from
# the given libdirs. The first argument will always be either
# $(LINK_c) or $(LINK_cxx). Note that that binbase has not been
# passed to $(binname). Compiler support implementors are
# encouraged to prepend the variable $(LINKWRAPPER) to link
# statements. This makes it possible for the user to set
# LINKWRAPPER to some program that wraps the link step. Examples of
# programs that do this include Purify and Quantify. NOTE: Your
# make_bin function should do something with the
# WHOLE_lib_$(libname) variables: either it should link in the whole
# library or issue an error that it is not supported. See
# toolchains/unix_compiler.mk and toolchains/msvc.mk for examples of
# each case.
#
# $(call make_shlib,linker,compiler-flags,link-flags,objects,lib-dirs,\
\libs,shlibbase,major,minor,revision):
# function that creates a library with the given base name. This
# function must take the same arguments as make_bin plus the shared
# library version information. Compiler support authors are
# encouraged to prepend the link statement with $(LINKWRAPPER) as
# with make_bin.
# When preparing to use a specific toolchain, please see comments in
# that toolchain's makefile fragment for any requirements that it may
# have.
# ---------------
TARGETS_lib ?=
TARGETS_bin ?=
# Make sure the user has asked for some targets.
ifeq ($(words $(TARGETS_lib) $(TARGETS_bin)), 0)
_qtx_dummy := $(call QTC.TC,abuild,ccxx.mk no targets,0)
$(error No ccxx targets are defined)
endif
# Separate TARGETS_lib into _TARGETS_static_lib and
# _TARGETS_shared_lib
_TARGETS_shared_lib := $(filter-out %:static,$(foreach L,$(TARGETS_lib),\
\$(L)$(if $(filter undefined,$(origin SHLIB_$(L))),:static)))
_TARGETS_static_lib := $(filter-out $(_TARGETS_shared_lib),$(TARGETS_lib))
# Define ccxx_shlibname to call shlibname with the right arguments
define ccxx_shlibname
$(call shlibname,$(1),$(word 1,$(SHLIB_$(1))),$(word 2,$(SHLIB_$(1))),$(\
\word 3,$(SHLIB_$(1))))
endef
# Define ccxx_all_shlibnames to get all variants of the shared library name
define ccxx_all_shlibnames
$(sort $(call shlibname,$(1),$(word 1,$(SHLIB_$(1))),$(word 2,$(SHLIB_$(\
\1))),$(word 3,$(SHLIB_$(1)))) \
$(call shlibname,$(1),$(word 1,$(SHLIB_$(1))),$(word 2,$(SHLIB_$(\
\1))),) \
$(call shlibname,$(1),$(word 1,$(SHLIB_$(1))),,) \
$(call shlibname,$(1),,,))
endef
# Add each target to the "all" and "clean" rules
_static_lib_TARGETS := $(foreach T,$(_TARGETS_static_lib),$(call libname,$(T)))
_shared_lib_TARGETS := $(foreach T,$(_TARGETS_shared_lib),$(call ccxx_sh\
\libname,$(T)))
_lib_TARGETS := $(_static_lib_TARGETS) $(_shared_lib_TARGETS)
_bin_TARGETS := $(foreach T,$(TARGETS_bin),$(call binname,$(T)))
all:: $(_lib_TARGETS) $(_bin_TARGETS)
# Add all local libraries to LIBS and all local library directories to
# LIBDIRS.
ifneq ($(words $(TARGETS_lib)),0)
LIBS := $(filter-out $(LIBS),$(_TARGETS_static_lib) $(_TARGETS_shared_li\
\b)) $(LIBS)
LIBDIRS := $(filter-out $(LIBDIRS),.) $(LIBDIRS)
endif
# Make sure that the user has provided sources for each target.
_UNDEFINED := $(call undefined_vars,\
$(foreach T,$(TARGETS_lib),SRCS_lib_$(T)) \
$(foreach T,$(TARGETS_bin),SRCS_bin_$(T)))
ifneq ($(words $(_UNDEFINED)),0)
_qtx_dummy := $(call QTC.TC,abuild,ccxx.mk undefined variables,0)
$(error The following variables are undefined: $(_UNDEFINED))
endif
# Basic compilation functions
DFLAGS ?=
OFLAGS ?=
WFLAGS ?=
XCPPFLAGS ?=
XCFLAGS ?=
XCXXFLAGS ?=
XLINKFLAGS ?=
LINKWRAPPER ?=
LINK_AS_C ?=
ifeq ($(ABUILD_SUPPORT_1_0),1)
ifneq ($(origin LINK_SHLIBS), undefined)
ifeq (-$(strip $(LINK_SHLIBS))-,--)
$(error setting LINK_SHLIBS to an empty value no longer works; overri\
\de LIBS instead)
else
$(call deprecate,1.1,LINK_SHLIBS is deprecated; as of version 1.0.3$(\
\_comma) abuild always links shared libraries)
endif
endif
endif
# These functions expand to the complete list of debug, optimization
# and warning flags that apply to a specific file. In this case,
# file-specific values override general values.
# Usage: $(call file_dflags,src)
define file_dflags
$(call value_if_defined,DFLAGS_$(call strip_srcdir,$(1)),$(DFLAGS))
endef
# Usage: $(call file_oflags,src)
define file_oflags
$(call value_if_defined,OFLAGS_$(call strip_srcdir,$(1)),$(OFLAGS))
endef
# Usage: $(call file_wflags,src)
define file_wflags
$(call value_if_defined,WFLAGS_$(call strip_srcdir,$(1)),$(WFLAGS))
endef
# Usage: $(call file_dowflags,src)
define file_dowflags
$(call file_dflags,$(1)) $(call file_oflags,$(1)) $(call file_wflags,$(1))
endef
# These functions expand to the complete list of "extra" flags that
# apply to a specific file. They are, from general to specific:
# XCPPFLAGS, then XCPPFLAGS_file (and similar for CFLAGS and
# CXXFLAGS). We use $(call value_if_defined ...) to access the
# file-specific variables to avoid the undefined variable warning for
# each undefined variable since not defining these is the usual case.
# Usage: $(call file_cppflags,src)
define file_cppflags
$(call include_flags,$(INCLUDES) $(SRCDIR) .) $(call file_dowflags,$(1))\
\ $(XCPPFLAGS) $(call value_if_defined,XCPPFLAGS_$(call strip_srcdir,$(1)),)
endef
# Usage: $(call file_cflags,src)
define file_cflags
$(call file_cppflags,$(1)) $(XCFLAGS) $(call value_if_defined,XCFLAGS_$(\
\call strip_srcdir,$(1)),)
endef
# Usage: $(call file_cxxflags,src)
define file_cxxflags
$(call file_cflags,$(1)) $(XCXXFLAGS) $(call value_if_defined,XCXXFLAGS_\
\$(call strip_srcdir,$(1)),)
endef
# Usage: $(call use_pic,src): determines the value of pic to pass to make_obj
define use_pic
$(and $(filter $(call strip_srcdir,$(<)), $(_lib_SRCS)), $(if $(call val\
\ue_if_defined,NOPIC_$(call strip_srcdir,$(<)),),,1))
endef
LANGNAME_c := C
LANGNAME_cxx := C++
CCXX_GEN_DEPS ?= $(GEN_DEPS)
CCCXX_LINKER = $(if $(LINK_AS_C),$(LINK_c),$(LINK_cxx))
# Usage: $(call ccxx_compile,language): language = { c | cxx }
define ccxx_compile
@: $(call QTC.TC,abuild,ccxx.mk ccxx_compile,0)
@mkdir -p $(dir $@)
$(CCXX_GEN_DEPS) \
"$(PREPROCESS_$(1)) $(call file_cppflags,$<)" \
"$<" "$@" "$*.$(DEP)"
-$(RM) $@
@$(PRINT) "Compiling $< as $(LANGNAME_$(1))"
$(call make_obj,$(COMPILE_$(1)),$(call use_pic,$<), \
$(call file_$(1)flags,$<),$<,$@)
endef
# Usage: $(call ccxx_preprocess,language): language = { c | cxx }
define ccxx_preprocess
@mkdir -p $(dir $@)
@$(PRINT) "Preprocessing $< as $(LANGNAME_$(1)) to $@"
-$(RM) $@
$(PREPROCESS_$(1)) $(call file_cppflags,$<) $< > $@
endef
# Usage: $(call ccxx_make_static_lib,library-base)
define ccxx_make_static_lib
@: $(call QTC.TC,abuild,ccxx.mk ccxx_make_static_lib,0)
-$(RM) $(call libname,$(1))
@$(PRINT) "Creating $(1) library"
$(call make_lib,$(OBJS_lib_$(1)),$(1))
endef
# Usage: $(call ccxx_make_shared_lib,library-base)
define ccxx_make_shared_lib
@: $(call QTC.TC,abuild,ccxx.mk ccxx_make_shared_lib,0)
@$(PRINT) "Creating $(1) shared library"
er-out $(_TARGETS_shared_lib),$(LIBS)),$(1),$(word 1,$(SHLIB_$(1))),$(wo\
\rd 2,$(SHLIB_$(1))),$(word 3,$(SHLIB_$(1))))
endef
# Usage: $(call ccxx_make_bin,executable-base)
define ccxx_make_bin
@: $(call QTC.TC,abuild,ccxx.mk ccxx_make_bin,0)
-$(RM) $(call binname,$(1))
@$(PRINT) "Creating $(1) executable"
$(call make_bin,$(CCCXX_LINKER),$(XCFLAGS) $(XCXXFLAGS) $(DFLAGS\
\) $(OFLAGS) $(WFLAGS),$(XLINKFLAGS),$(OBJS_bin_$(1)),$(LIBDIRS),$(LIBS),$(1))
endef
c_to_o = $(call ccxx_compile,c)
cxx_to_o = $(call ccxx_compile,cxx)
lib_c_to_o = $(c_to_o)
bin_c_to_o = $(c_to_o)
lib_cxx_to_o = $(cxx_to_o)
bin_cxx_to_o = $(cxx_to_o)
c_to_i = $(call ccxx_preprocess,c)
cxx_to_i = $(call ccxx_preprocess,cxx)
# For each SRCS_lib_x and SRCS_bin_x, create corresponding OBJS_lib_x
# and OBJS_bin_x by transforming all .c, .cc, and .cpp file names to
# object file names.
$(foreach T,$(TARGETS_lib),\
$(eval OBJS_lib_$(T) := \
$(call x_to_y,c,$(LOBJ),SRCS_lib_$(T)) \
$(call x_to_y,cc,$(LOBJ),SRCS_lib_$(T)) \
$(call x_to_y,cpp,$(LOBJ),SRCS_lib_$(T))))
$(foreach T,$(TARGETS_bin),\
$(eval OBJS_bin_$(T) := \
$(call x_to_y,c,$(OBJ),SRCS_bin_$(T)) \
$(call x_to_y,cc,$(OBJ),SRCS_bin_$(T)) \
$(call x_to_y,cpp,$(OBJ),SRCS_bin_$(T))))
# Combine all sources from various bases into types (lib and bin) and
# then separate by suffix. These variables are used for static pattern
# rules to invoke the correct compilation steps for files based on
# suffix and target type.
_lib_SRCS := $(sort $(foreach T,$(TARGETS_lib),$(SRCS_lib_$(T))))
_bin_SRCS := $(sort $(foreach T,$(TARGETS_bin),$(SRCS_bin_$(T))))
_all_SRCS := $(sort $(_lib_SRCS) $(_bin_SRCS))
_lib_COBJS := $(call x_to_y,c,$(LOBJ),_lib_SRCS)
_lib_CCOBJS := $(call x_to_y,cc,$(LOBJ),_lib_SRCS)
_lib_CPPOBJS := $(call x_to_y,cpp,$(LOBJ),_lib_SRCS)
_bin_COBJS := $(call x_to_y,c,$(OBJ),_bin_SRCS)
_bin_CCOBJS := $(call x_to_y,cc,$(OBJ),_bin_SRCS)
_bin_CPPOBJS := $(call x_to_y,cpp,$(OBJ),_bin_SRCS)
_Cpproc := $(call x_to_y,c,i,_lib_SRCS) $(call x_to_y,c,i,_bin_SRCS)
_CCpproc := $(call x_to_y,cc,i,_lib_SRCS) $(call x_to_y,cc,i,_bin_SRCS)
_CPPpproc := $(call x_to_y,cpp,i,_lib_SRCS) $(call x_to_y,cpp,i,_bin_SRCS)
# Make sure ".." doesn't appear in any source file names.
ifneq ($(words $(findstring /../,$(_all_SRCS)) $(filter ../%,$(_all_SRCS))), 0)
_qtx_dummy := $(call QTC.TC,abuild,ccxx.mk ERR .. in srcs,0)
$(error The path component ".." may not appear in any source file names)
endif
# Include dependency files for each source file
_lib_OBJS := $(_lib_COBJS) $(_lib_CCOBJS) $(_lib_CPPOBJS)
_bin_OBJS := $(_bin_COBJS) $(_bin_CCOBJS) $(_bin_CPPOBJS)
_all_DEPS := $(call x_to_y,$(LOBJ),$(DEP),_lib_OBJS) \
$(call x_to_y,$(OBJ),$(DEP),_bin_OBJS)
# Remove any extraneous dep files
_extra_deps := $(filter-out $(_all_DEPS),$(wildcard *.$(DEP)))
ifneq ($(words $(_extra_deps)),0)
_qtx_dummy := $(call QTC.TC,abuild,ccxx.mk remove extra deps,0)
DUMMY := $(shell $(PRINT) 1>&2 Removing extraneous $(DEP) files)
DUMMY := $(shell $(RM) $(_extra_deps))
endif
-include $(_all_DEPS)
# Define static pattern rules that invoke the proper compilation
# function for each object file.
$(_lib_COBJS): %.$(LOBJ): %.c
$(lib_c_to_o)
$(_lib_CCOBJS): %.$(LOBJ): %.cc
$(lib_cxx_to_o)
$(_lib_CPPOBJS): %.$(LOBJ): %.cpp
$(lib_cxx_to_o)
$(_bin_COBJS): %.$(OBJ): %.c
$(bin_c_to_o)
$(_bin_CCOBJS): %.$(OBJ): %.cc
$(bin_cxx_to_o)
$(_bin_CPPOBJS): %.$(OBJ): %.cpp
$(bin_cxx_to_o)
$(_Cpproc): %.i: %.c FORCE
$(c_to_i)
$(_CCpproc): %.i: %.cc FORCE
$(cxx_to_i)
$(_CPPpproc): %.i: %.cpp FORCE
$(cxx_to_i)
# Ensure that we can use -llib dependencies properly.
.LIBPATTERNS ?=
$(foreach PAT,$(.LIBPATTERNS),$(eval vpath $(PAT) $(LIBDIRS)))
# For each library and executable target, create a rule that makes the
# target dependent on its objects. Also make executable targets
# depend on the libraries in LIBS, which includes local libraries,
# and shared libary targets depend on the static libraries in LIBS.
# In addition, we make local executable targets explicitly depend on
# local library targets. The reason for doing this as well as adding
# the -llib target for local libraries is that make will not try to
# build the -llib target if it doesn't exist.
l_LIBS = $(foreach L,$(LIBS),-l$(L))
l_not_local_shared = $(foreach L,$(filter-out $(_TARGETS_shared_lib),$(L\
\IBS)),-l$(L))
$(foreach T,$(_TARGETS_static_lib),\
$(eval $(call libname,$(T)): $(OBJS_lib_$(T)) ; \
$(call ccxx_make_static_lib,$(T))))
$(foreach T,$(_TARGETS_shared_lib),\
$(eval $(call ccxx_shlibname,$(T)): $(OBJS_lib_$(T)) $(l_not_local_sh\
\ared) $(_static_lib_TARGETS); \
$(call ccxx_make_shared_lib,$(T))))
$(foreach T,$(TARGETS_bin),\
$(eval $(call binname,$(T)): $(OBJS_bin_$(T)) $(l_LIBS) $(_lib_TARGETS); \
$(call ccxx_make_bin,$(T))))
# For each local library target x that does not exist, make -lx depend
# on $(call libname,x). This prevents errors about -lx not existing
# when a binary target is built explicitly from clean. We avoid
# creating this dependency if the library already exists because
# otherwise make will translate this into a circular dependency when
# it replaces -lx with the actual library file in the rule.
$(foreach T,$(_TARGETS_static_lib),\
$(eval -l$(T): $(if $(wildcard $(call libname,$(T))),,$(call libname,\
\$(T)))))
$(foreach T,$(_TARGETS_shared_lib),\
$(eval -l$(T): $(if $(wildcard $(call ccxx_shlibname,$(T))),,$(call c\
\cxx_shlibname,$(T)))))
_all_obj := $(sort $(_lib_OBJS) $(_bin_OBJS))
# The list of all libraries includes static versions of the shared
# libraries as well since on some platforms (Windows), creating a
# shared library also creates a static library of the same name.
_all_lib := $(sort \
$(foreach T,$(TARGETS_lib),$(call libname,$(T))) \
$(foreach T,$(_TARGETS_shared_lib),$(call ccxx_all_shlibnames,$(T))))
_all_bin := $(foreach T,$(TARGETS_bin),$(call binname,$(T)))
# Check for and remove orphan targets
IGNORE_TARGETS ?=
_existing_obj := $(sort $(wildcard *.$(OBJ) *.$(LOBJ)))
_extra_obj := $(filter-out $(_all_obj) $(IGNORE_TARGETS),$(_existing_obj))
ifeq ($(words $(_extra_obj)),0)
# No extra objects found; check for other extra targets. Check for
# libraries and shared libraries, and if we can recognize executables
# as such (they have some recognizable suffix), check for them as
# well.
_all_other := $(_all_lib)
_existing_other := $(sort $(wildcard $(call libname,*) $(call shlibname\
\,*,,,)))
ifneq ($(call binname,*),*)
# If executables are recognizable as such
_all_other += $(_all_bin)
_existing_other += $(sort $(wildcard $(call binname,*)))
endif
_extra_other := $(filter-out $(_all_other) $(IGNORE_TARGETS),$(_existin\
\g_other))
ifneq ($(words $(_extra_other)),0)
_qtx_dummy := $(call QTC.TC,abuild,ccxx.mk found extra other,0)
# For all binary and library targets to relink
DUMMY := $(shell $(PRINT) 1>&2 Extra targets found: removing libraries\
\ and binaries)
DUMMY := $(shell $(RM) $(_extra_other) $(_all_lib) $(_all_bin))
endif
else
# Extra object files found; remove all extra objects as well as any
# library or binary targets which we want to force to be recreated.
_qtx_dummy := $(call QTC.TC,abuild,ccxx.mk found extra objs,0)
DUMMY := $(shell $(PRINT) 1>&2 Extra object files found: removing libra\
\ries and binaries)
DUMMY := $(shell $(RM) $(_extra_obj) $(_all_lib) $(_all_bin))
endif
# Create a debugging target that shows values of some critical
# variables.
.PHONY: ccxx_debug
ccxx_debug::
@: $(call QTC.TC,abuild,ccxx.mk ccxx_debug,0)
@$(PRINT) INCLUDES = $(INCLUDES)
@$(PRINT) LIBDIRS = $(LIBDIRS)
@$(PRINT) LIBS = $(LIBS)
# Include built-in support for certain code generators. These should
# have been plugins, but they were added before plugins were
# supported.
include $(abMK)/standard-code-generators.mk