# Version for Linux/RTLinux builds. # # # input variables # lib_LIBRARIES .. list of the user-space libraries # shared_LIBRARIES .. list of the user-space shared libraries # include_HEADERS .. list of the user-space public header files # nobase_include_HEADERS .. public headers copied even with directory part # renamed_include_HEADERS .. public headers copied to the different target name # bin_PROGRAMS .. list of the require binary programs # utils_PROGRAMS .. list of the development utility programs # test_PROGRAMS .. list of the testing programs # bin_SCRIPTS .. list of scripts to be copied to _compiled/bin # xxx_SOURCES .. list of specific target sources # xxx_LIBS .. list of specific target libraries (-l prefix is automatically added) # xxx_LDFLAGS .. list of specific target LDFLAGS # lib_LOADLIBES .. list of libraries linked to each executable # INCLUDES .. additional include directories and defines for user-space # # AM_CFLAGS .. C compiler flags # AM_CXXFLAGS .. C++ compiler flags # AM_CPPFLAGS .. C preprocessor flags # LDFLAGS .. linker flags for programs linking BUILD_DIR_NAME = _build COMPILED_DIR_NAME = _compiled ifndef GROUP_DIR_NAME GROUP_DIR_NAME = nogroup endif USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include USER_LIB_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib USER_UTILS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils USER_TESTS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests USER_BIN_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin USER_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user ifeq ($(BUILD_OS),) # Check for target ifeq ($(OS),Windows_NT) BUILD_OS := win32 else BUILD_OS := $(shell uname | tr '[A-Z]' '[a-z]' ) #$(warning BUILD_OS=$(BUILD_OS)) endif endif ifeq ($(TARGET_OS),) TARGET_OS := $(BUILD_OS) endif export TARGET_OS export BUILD_OS LOCAL_BUILD_DIR = $(USER_OBJS_DIR) # Assign default values to CFLAGS variable. If the variable is defined # earlier (i.g. in config.omk), it is not overriden here. CFLAGS ?= -O2 -Wall CXXFLAGS ?= -O2 -Wall CPPFLAGS += -I $(USER_INCLUDE_DIR) LOADLIBES += -L$(USER_LIB_DIR) LOADLIBES += $(lib_LOADLIBES:%=-l%) LIB_CPPFLAGS += $(CPPFLAGS) LIB_CFLAGS += $(CFLAGS) ifeq ($(TARGET_OS),win32) EXE_SUFFIX = .exe SOLIB_EXT = dll else SOLIB_EXT = so SOLIB_PICFLAGS += -fpic endif #vpath %.c $(SOURCES_DIR) #vpath %.cc $(SOURCES_DIR) #vpath %.cxx $(SOURCES_DIR) USER_OBJS_DIR = $(USER_BUILD_DIR)/$(RELATIVE_DIR) OMK_WORK_DIR = $(USER_OBJS_DIR) .PHONY: dep subdirs clean clean-custom cleandepend check-dir # Some support to serialize some targets for parallel make ifneq ($(OMK_SERIALIZE_INCLUDED),y) include-pass: check-dir library-pass: include-pass link-pseudo-pass: library-pass binary-pass: link-pseudo-pass override OMK_SERIALIZE_INCLUDED = y MAKEOVERRIDES := $(filter-out OMK_SERIALIZE_INCLUDED=n,$(MAKEOVERRIDES)) endif #===================================================================== # User-space rules and templates to compile programs, libraries etc. ifdef USER_RULE_TEMPLATES c_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER cc_o_COMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -DOMK_FOR_USER S_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(ASFLAGS) -DOMK_FOR_USER idl_COMPILE = $(IDL_COMPILER) # Check GCC version for user build ifndef CC_MAJOR_VERSION CC_MAJOR_VERSION := $(shell $(CC) -dumpversion | $(SED4OMK) -e 's/\([^.]\)\..*/\1/') endif # Prepare suitable define for dependency building ifeq ($(CC_MAJOR_VERSION),2) CC_DEPFLAGS = -Wp,-MD,"$@.d.tmp" else CC_DEPFLAGS = -MT $@ -MD -MP -MF "$@.d.tmp" endif # Syntax: $(call COMPILE_c_o_template,,,) define COMPILE_c_o_template ifeq ($$($(2)_C_TARGET),) $(2)_C_TARGET=1 $(2): $(1) $$(GEN_HEADERS) @$(QUIET_CMD_ECHO) " CC $$@" $(Q) if $$(c_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \ then mv -f "$$@.d.tmp" "$$@.d" ; \ else rm -f "$$@.d.tmp" ; exit 1; \ fi endif endef # Syntax: $(call COMPILE_cc_o_template,,,) define COMPILE_cc_o_template ifeq ($$($(2)_CC_TARGET),) $(2)_CC_TARGET=1 $(2): $(1) $$(GEN_HEADERS) @$(QUIET_CMD_ECHO) " CXX $$@" $(Q) if $$(cc_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \ then mv -f "$$@.d.tmp" "$$@.d" ; \ else rm -f "$$@.d.tmp" ; exit 1; \ fi endif endef # Syntax: $(call COMPILE_S_o_template,,,) define COMPILE_S_o_template ifeq ($$($(2)_S_TARGET),) $(2)_S_TARGET=1 $(2): $(1) $$(GEN_HEADERS) @$(QUIET_CMD_ECHO) " AS $$@" $(Q) if $$(S_o_COMPILE) -D__ASSEMBLY__ $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \ then mv -f "$$@.d.tmp" "$$@.d" ; \ else rm -f "$$@.d.tmp" ; exit 1; \ fi endif endef NM ?= nm # Syntax: $(call CMETRIC_o_h_template,,) define CMETRIC_o_h_template $(2): $(1) @$(QUIET_CMD_ECHO) " CMETRIC $$@" $(Q)if [ -n `dirname $$@` ] ; then \ if [ ! -e `dirname $$@` ] ; then \ mkdir -p `dirname $$@` ; fi ; fi $(Q)echo >$$@.tmp '/* Automatically generated from $$< */' $(Q)echo >>$$@.tmp '/* Conditionals to control compilation */' # Bellow, the tricks with redirection are for shells without set -o pipefail # (see http://www.mail-archive.com/dash@vger.kernel.org/msg00149.html) $(Q)exec 3>&1; status=`exec 4>&1 >&3; { $(NM) $$<; echo $$$$? >&4; }\ | $(SED4OMK) -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2cond_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \ | sort >>$$@.tmp` && exit $$$$status $(Q)echo >>$$@.tmp '/* Defines from the values defined to symbols in hexadecimal format */' $(Q)exec 3>&1; status=`exec 4>&1 >&3; { $(NM) $$<; echo $$$$? >&4; }\ | $(SED4OMK) -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2def_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \ | sort >>$$@.tmp` && exit $$$$status $(Q)echo >>$$@.tmp '/* Defines from the values defined to symbols in decimal format */' $(Q)exec 3>&1; status=`exec 4>&1 >&3; { $(NM) -td $$<; echo $$$$? >&4; }\ | $(SED4OMK) -n 's/^ *0*\(0\|[1-9][0-9]*\) *A *_cmetric2defdec_\([A-Za-z_0-9]*\) */#define \2 \1/p' \ | sort >>$$@.tmp` && exit $$$$status $(Q)mv $$@.tmp $$@ endef # Syntax: $(call COMPILE_idl_template,,) define COMPILE_idl_template ifeq ($$($(2)_IDL_TARGET),) $(2)_IDL_TARGET=1 GEN_HEADERS+=$(filter %.h,$(notdir $(1:%.idl=%.h))) # Do we need this global variable? $(2).c $(2)-stubs.c $(2)-skels.c $(2)-common.c $(2).h: $(1) $$(wildcard $$(firstword $$(idl_COMPILE))) @$(QUIET_CMD_ECHO) " IDL $$@" $(Q) $$(idl_COMPILE) $$($(2)_IDLFLAGS) $(1) endif endef # Syntax: $(call COMPILE_templates,,) # Note: The newlines after $(call ) are IMPORTANT!!! define COMPILE_templates $(foreach src,$(filter %.c,$(1)),$(call COMPILE_c_o_template,$(src),$(notdir $(src:%.c=%$(2))),) ) $(foreach src,$(filter %.cc,$(1)),$(call COMPILE_cc_o_template,$(src),$(notdir $(src:%.cc=%$(2))),) ) $(foreach src,$(filter %.cxx,$(1)),$(call COMPILE_cc_o_template,$(src),$(notdir $(src:%.cxx=%$(2))),) ) $(foreach src,$(filter %.cpp,$(1)),$(call COMPILE_cc_o_template,$(src),$(notdir $(src:%.cpp=%$(2))),) ) $(foreach src,$(filter %.S,$(1)),$(call COMPILE_S_o_template,$(src),$(notdir $(src:%.S=%$(2))),) ) endef TARGET_GEN_SOURCES = $(filter %.c,$($(1)_SERVER_IDL:%.idl=%-skels.c)) \ $(filter %.c,$($(1)_SERVER_IDL:%.idl=%-common.c)) \ $(filter %.c,$($(1)_CLIENT_IDL:%.idl=%-stubs.c)) \ $(filter %.c,$($(1)_CLIENT_IDL:%.idl=%-common.c)) \ $(filter %.c,$($(1)_IDL:%.idl=%.c)) TARGET_SOURCES = $($(1)_SOURCES) $(TARGET_GEN_SOURCES) TARGET_SOURCES_ABS = $($(1)_SOURCES:%=$(SOURCES_DIR)/%) $(TARGET_GEN_SOURCES) TARGET_OBJS = $(sort $(addsuffix .o,$(basename $(notdir $(TARGET_SOURCES))))) TARGET_LOBJS = $(sort $(addsuffix .lo,$(basename $(notdir $(TARGET_SOURCES))))) TARGET_IDLS = $($(1)_SERVER_IDL) $($(1)_CLIENT_IDL) $($(1)_IDL) LINK_WITH_CXX = $(filter %.cc,$(TARGET_SOURCES))$(filter %.cxx,$(TARGET_SOURCES))$$(filter %.cpp,$(TARGET_SOURCES)) # Syntax: $(call PROGRAM_template,,,,) define PROGRAM_template $(foreach idl,$(TARGET_IDLS),$(call COMPILE_idl_template,$(SOURCES_DIR)/$(idl),$(idl:%.idl=%))) $(call COMPILE_templates,$(TARGET_SOURCES_ABS),.o) $(2)/$(1)$(3): $(TARGET_OBJS) @$(QUIET_CMD_ECHO) " LINK $$@" $(Q) $(if $(LINK_WITH_CXX),$$(CXX),$$(CC)) \ $$^ $$($(1)_LIBS:%=-l%) $$(LOADLIBES) $$(AM_LDFLAGS) $$(LDFLAGS) $$($(1)_LDFLAGS) -Wl,-rpath-link,$(USER_LIB_DIR) -Wl,-Map,$(USER_OBJS_DIR)/$(1).exe.map -o $$@ @echo "$(2)/$(1)$(3): \\" >$(USER_OBJS_DIR)/$(1).exe.d @$(SED4OMK) -n -e 's|^LOAD \(.*\)$$$$| \1 \&|p' $(USER_OBJS_DIR)/$(1).exe.map|tr '&' '\134' >>$(USER_OBJS_DIR)/$(1).exe.d @echo >>$(USER_OBJS_DIR)/$(1).exe.d binary-pass-local: $(2)/$(1)$(3) endef # Usage: $(call SCRIPT_template,,) define SCRIPT_template $(2)/$(1): $$(SOURCES_DIR)/$(1) @$(QUIET_CMD_ECHO) " CP $$@" $(Q)cp $$^ $$@ binary-pass-local: $(2)/$(1) endef # Syntax: $(call LIBRARY_template,) define LIBRARY_template $(foreach idl,$(TARGET_IDLS),$(call COMPILE_idl_template,$(SOURCES_DIR)/$(idl),$(idl:%.idl=%))) $(call COMPILE_templates,$(TARGET_SOURCES_ABS),.o) $(USER_LIB_DIR)/lib$(1).a: $(TARGET_OBJS) @$(QUIET_CMD_ECHO) " AR $$@" $(Q) $(AR) rcs $$@ $$^ library-pass-local: $(USER_LIB_DIR)/lib$(1).a endef # Syntax: $(call SOLIB_template,) define SOLIB_template $(foreach idl,$(TARGET_IDLS),$(call COMPILE_idl_template,$(SOURCES_DIR)/$(idl),$(idl:%.idl=%))) $(call COMPILE_templates,$(TARGET_SOURCES_ABS),.lo) .PHONY: $(OMK_WORK_DIR)/lib$(1).$(SOLIB_EXT).omkvar $(OMK_WORK_DIR)/lib$(1).$(SOLIB_EXT).omkvar: AM_CFLAGS += $(SOLIB_PICFLAGS) $(OMK_WORK_DIR)/lib$(1).$(SOLIB_EXT).omkvar: AM_CXXFLAGS += $(SOLIB_PICFLAGS) $(OMK_WORK_DIR)/lib$(1).$(SOLIB_EXT).omkvar: $(TARGET_LOBJS) $(Q)echo '$(1)_objslo += $$$$(addprefix $(USER_OBJS_DIR)/,$$^)' > $$@.tmp; \ echo '$(1)_libs += $$($(1)_LIBS) $$(lib_LOADLIBES)' >> $$@.tmp; \ echo '$(1)_ldflags += $$($(1)_LDFLAGS) $$(lib_LDFLAGS)' >> $$@.tmp; \ echo 'shared_libs := $$$$(sort $(1) $$$$(shared_libs))' >> $$@.tmp; \ if cmp -s $$@.tmp $$@; then rm $$@.tmp; else mv $$@.tmp $$@; fi library-pass-local: $(OMK_WORK_DIR)/lib$(1).$(SOLIB_EXT).omkvar endef library-pass-local: $(addprefix $(USER_INCLUDE_DIR)/,$(cmetric_include_HEADERS)) \ # Special rules for CMETRIC generated headers $(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call COMPILE_c_o_template,\ $(SOURCES_DIR)/$($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES),\ $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),))) $(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call CMETRIC_o_h_template,\ $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),\ $(addprefix $(USER_INCLUDE_DIR)/,$(cmetrh))))) GEN_HEADERS+=$(cmetric_include_HEADERS:%=$(USER_INCLUDE_DIR)/%) # Generate rules for compilation of programs and libraries $(foreach prog,$(utils_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_UTILS_DIR),$(EXE_SUFFIX)))) $(foreach prog,$(test_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_TESTS_DIR),$(EXE_SUFFIX)))) $(foreach prog,$(bin_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_BIN_DIR),$(EXE_SUFFIX)))) $(foreach script,$(bin_SCRIPTS),$(eval $(call SCRIPT_template,$(script),$(USER_BIN_DIR)))) $(foreach lib,$(lib_LIBRARIES),$(info $(call LIBRARY_template,$(lib)))) $(foreach lib,$(lib_LIBRARIES),$(eval $(call LIBRARY_template,$(lib)))) $(foreach lib,$(shared_LIBRARIES),$(eval $(call SOLIB_template,$(lib)))) -include $(USER_OBJS_DIR)/*.d #FIXME: This doesn't include dependencies of source files from #subdirectories (i.s. *_SOURCES=dir/file.c. I'm currently not sure, #how to handle this. endif # USER_RULE_TEMPLATES .PHONY: link-pseudo-pass link-pseudo-pass: $(Q)$(MAKE) $(NO_PRINT_DIRECTORY) -C $(USER_BUILD_DIR) -f $(SOURCESDIR_MAKEFILE) link-shared-libs ifeq ($(MAKECMDGOALS),link-shared-libs) # Syntax: $(call solib_link_template,) define solib_link_template $(1)_shared_libs = $$(patsubst %,$(USER_LIB_DIR)/lib%.$(SOLIB_EXT),$$(filter $$(shared_libs),$$($(1)_libs))) #$$(warning $(1)_shared_libs = $$($(1)_shared_libs)) $(USER_LIB_DIR)/lib$(1).$(SOLIB_EXT): $$($(1)_shared_libs) $$($(1)_objslo) @$(QUIET_CMD_ECHO) " LINK $$@" $(Q)$(CC) --shared -Xlinker -soname=lib$(1).$(SOLIB_EXT) -Wl,-Map,$(USER_OBJS_DIR)/lib$(1).$(SOLIB_EXT).map -o $$@ $$($(1)_objslo) $$(LOADLIBES) $$($(1)_libs:%=-l%) $$(lib_ldflags) $$($(1)_ldflags) endef -include $(shell true; find $(USER_BUILD_DIR) -name 'lib*.omkvar') # `true' is a hack for MinGW #$(warning $(shared_libs)) $(foreach lib,$(shared_libs),$(eval $(call solib_link_template,$(lib)))) .PHONY: link-shared-libs link-shared-libs: $(shared_libs:%=$(USER_LIB_DIR)/lib%.$(SOLIB_EXT)) endif # link-shared-libs $(eval $(call omk_pass_template, library-pass,$(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,$(lib_LIBRARIES)$(shared_LIBRARIES))) $(eval $(call omk_pass_template, binary-pass, $(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,$(bin_PROGRAMS)$(utils_PROGRAMS)$(test_PROGRAMS)$(bin_SCRIPTS))) $(eval $(call omk_pass_template,clean,$(USER_OBJS_DIR),,always)) $(eval $(call omk_pass_template,install,$(USER_OBJS_DIR),,always)) $(eval $(call omk_pass_template,include-pass,$(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,always)) check-dir:: @$(call mkdir_def,$(USER_BUILD_DIR)) @$(call mkdir_def,$(USER_INCLUDE_DIR)) @$(call mkdir_def,$(USER_LIB_DIR)) @$(call mkdir_def,$(USER_BIN_DIR)) @$(call mkdir_def,$(USER_UTILS_DIR)) @$(call mkdir_def,$(USER_TESTS_DIR)) install-local: # TODO $(eval $(call include-pass-template,$(USER_INCLUDE_DIR),include)) clean-local:: @echo Cleaning in $(USER_OBJS_DIR) @rm -f $(USER_OBJS_DIR)/*.[och] \ $(USER_OBJS_DIR)/*.lo \ $(USER_OBJS_DIR)/*.d \ $(USER_OBJS_DIR)/*.map \ $(LOCAL_CONFIG_H:%=$(USER_OBJS_DIR)/%) include-pass-submakes: extra-rules-subdirs # We must go to EXTRA_RULES_SUBDIRS before going to any other # directory, since the executables compiled in EXTRA_RULES_SUBDIRS # might be needed there. include-pass-this-dir $(foreach subdir,$(SUBDIRS),include-pass-$(subdir)-subdir): extra-rules-subdirs default: include-pass library-pass binary-pass