From 695d24d66eff41e489c7016798da5311bf81777e Mon Sep 17 00:00:00 2001 From: ken Date: Tue, 1 Nov 2016 19:58:22 -0700 Subject: [PATCH] makefile fixes, moved the linking subsystem to driver-rule-reckoning --- Makefile | 5 +- make/lib/awk.mk | 5 +- make/lib/rules.mk | 145 +++++++++++++++++++++++----------------------- 3 files changed, 74 insertions(+), 81 deletions(-) diff --git a/Makefile b/Makefile index a8aefba..d10e17b 100644 --- a/Makefile +++ b/Makefile @@ -28,11 +28,9 @@ SLANGS := y rl # Language-specific compilers and flags passed in from environment c_C := $(strip $(notdir $(CC))) c_FLAGS := $(strip $(CFLAGS)) -I$(SRC_DIR) -c_LIBS := SDL2 wolfssl unistring c_SRCL := y cpp_C := $(strip $(notdir $(CXX))) cpp_FLAGS := $(strip $(CXXFLAGS)) $(c_FLAGS) -cpp_LIBS := $(c_LIBS) go_C := gccgo go_FLAGS := $(c_FLAGS) # Source to source languages @@ -73,7 +71,7 @@ gccgo_LD := $(cc_LD) gccgo_AR := $(cc_AR) gccgo_AROBJ := $(cc_AROBJ) # Shell functions to determine what libraries can be linked by the compiler -cc_LDLIBS := $(shell ls /usr/lib | grep ".o" | sed -e 's@^.*lib\([_\+a-zA-Z0-9\-]*\)\..*@\1@g') +cc_LDLIBS := $(shell ldconfig -p | sed -e 's@\-*[0-9\.]*\.so.*$$@@g' -e 's@\tlib@@g' -e '/[\t ]/d') gcc_LDLIBS := $(cc_LDLIBS) emcc_LDLIBS := g++_LDLIBS := $(cc_LDLIBS) @@ -116,7 +114,6 @@ $(eval CVSROOT_BAK := $(CVSROOT))) ifdef LANG_INIT $(foreach lang,$(LANGS),\ $(eval $(call LANG_INIT,$(lang)))\ -$(eval $(lang)_LIBS := $(shell echo $($(lang)_LIBS | $(call AWK_REVERSE_SQUASH))))\ ) else $(error No LANG_INIT available, no languages can be compiled) diff --git a/make/lib/awk.mk b/make/lib/awk.mk index 81b57ca..bedd8bc 100644 --- a/make/lib/awk.mk +++ b/make/lib/awk.mk @@ -16,9 +16,8 @@ define AWK_REVERSE_SQUASH = awk \ ' { for(i=NF;i>0;i--) - printf (!a[$$i]++) ? $$i FS : ""; - i=split("",a); - print "" + if (!a[$$i]++) + print $$i } ' #/AWK_REVERSE_SQUASH############################################################ diff --git a/make/lib/rules.mk b/make/lib/rules.mk index 50ca62b..8bac388 100644 --- a/make/lib/rules.mk +++ b/make/lib/rules.mk @@ -42,6 +42,13 @@ $(eval MAKE_TARGETS += $(SRC_OBJ)) $(foreach lost,$(LOST), $(eval ALLDEPS := $(subst $(lost), $(dir $1)$(lost),$(ALLDEPS)))) +# Find relative deps in our local LIBINC_DIR, if available. Otherwise they +# should be expected in the src directory +$(eval RELDEPS := $(filter-out $(SRC_DIR:./%=%)/% ./% /%,$(ALLDEPS))) +$(foreach dep,$(RELDEPS), +$(eval ALLDEPS := $(subst $(dep),\ +$(if $(wildcard $(LIBINC_DIR)/$(dep)),$(LIBINC_DIR),$(SRC_DIR))/$(dep),$(ALLDEPS)))) + # Find any deps that aren't built yet, which the compiler has flagged # as missing, but which we know the expected location of libs for # this language should have their includes in 'LIBINC_DIR' @@ -65,9 +72,11 @@ endef #SRC_LANG_DRVRULE################################################################ # establish a build and link rule given a source driver and language ############ define SRC_LANG_DRVRULE = -$(eval DRIVER_NAME := $(basename $(notdir $1))) -$(eval DRIVER_TARG := $(1:$(SRC_DIR)/%.$2=$(ROOT_DIR)/%$($2_OUT))) -$(eval DRIVER_SOB := $(basename $1).$($2_OBJ)) +$(eval DRIVER_NAME := $(basename $(notdir $1))) +$(eval DRIVER_TARG := $(1:$(SRC_DIR)/%.$2=$(ROOT_DIR)/%$($2_OUT))) +$(eval DRIVER_TARG_D := $(DRIVER_TARG)-d) +$(eval DRIVER_SOB := $(basename $1).$($2_OBJ)) +$(eval DRIVER_SOB_D := $(DRIVER_SOB:$(dir $(DRIVER_SOB))%=$(dir $(DRIVER_SOB)).$($2_DBG)/%)) # Generate a rule for the driver object $(eval $(call SRC_LANG_RULE,$1,$2)) @@ -80,75 +89,68 @@ $(eval DRIVER_MODULES += $(firstword $(subst /, ,$(module_dep)))) ) $(eval DRIVER_MODULES := $(filter-out $(DRIVER_DIR) . ..,$(sort $(DRIVER_MODULES)))) -# In the event that the driver developer does not wish to include a header to -# any internal modules, the developer may instead create a file with the same -# basename as the driver, but with the '.ld' suffix, which contains a space -# separated list of internal modules to link together during compilation -$(eval DRIVER_LDVALS := $(file <$(1:%.$2=%.ld))) -$(eval DRIVER_LFLAGS := $(filter -l%,$(DRIVER_LDVALS))) -$(eval DRIVER_MODULES += $(filter-out -l%,$(DRIVER_LDVALS))) -$(eval DRIVER_MODULES := $(sort $(DRIVER_MODULES))) -# List of module archives to link together during compilation -$(eval DRIVER_ARCHIVES := $(DRIVER_MODULES:%=$(SRC_DIR)/%.$($2_AROBJ))) -$(eval DRIVER_DEPS := $(DRIVER_SOB) $(DRIVER_ARCHIVES)) -$(eval DRIVER_DBGARCHIVES := $(DRIVER_MODULES:%=$(SRC_DIR)/.$($2_DBG)/%.$($2_AROBJ))) -$(eval DRIVER_DBGDEPS := $(dir $(DRIVER_SOB)).$($2_DBG)/$(notdir $(DRIVER_SOB))) -$(eval DRIVER_DBGDEPS += $(DRIVER_DBGARCHIVES)) - -# If the compiler supports linking, distinguish static from dynamic links, -# otherwise set all libraries to static -$(if $($($2_C)_LD),\ -$(eval STLIBS := $(filter-out $($($2_C)_LDLIBS),$($2_LIBS)))\ -$(eval DLIBS := $(filter-out $(STLIBS),$($2_LIBS))),\ -$(eval STLIBS := $($2_LIBS))) +# Read associated linking data for the driver. If no link data is available, +# all libraries are assumed to be statically linked by the build system. files +# prefixed with 'test' will first attempt to find a 'ld' file matching its +# basename with the 'test' prefix removed (i.e. ./src/bin/testscanner.c will +# first attempt to find ./src/bin/scanner.ld for its ld information. if not +# available, it will instead use ./src/bin/testscanner.ld. if still not +# available, all libraries will attempt static linking - and if those static +# libs are not available, the system will attempt to retrieve the source code +# and build the static lib +$(eval DRIVER_LDFILE := $(1:%.$2=%.ld)) +$(if $(filter test%,$(DRIVER_NAME)), +$(eval DRV_LD := $(subst $(DRIVER_NAME).$2,$(DRIVER_NAME:test%=%).ld,$1)) +$(if $(wildcard $(DRV_LD)), +$(eval DRIVER_LDFILE := $(DRV_LD)) +)) +$(eval $1_LD := $(file <$(DRIVER_LDFILE))) +$(eval undefine DRIVER_LDINFO) +$(eval undefine DRIVER_LDINFO_D) +$(foreach ldobj,$($1_LD), +$(if $(filter -l%,$(ldobj)), +$(eval ldlibname := $(ldobj:-l%=%)) +$(if $(filter $(ldlibname),$($($2_C)_LDLIBS)), +$(eval DRIVER_LDINFO += $(ldobj)) +$(eval DRIVER_LDINFO_D += $(ldobj)), +$(info Statically linking '$(ldobj:-l%=lib%)', linker '$($($2_C)_LD)' for compiler '$($2_C)' cannot link this lib.) +$(if $($(ldlibname)_INIT),,$(call LANG_LIB_INIT,$2,$(ldlibname),$1)) +$(foreach deplib,$($(ldlibname)_DEPS) $(ldlibname), +$(eval DRIVER_LDINFO += $(LIB_DIR)/$(deplib).$($2_AROBJ)) +$(eval DRIVER_LDINFO_D += $(LIB_DIR)/.$($2_DBG)/$(deplib).$($2_AROBJ))) +), +$(if $(findstring $(ldobj),$(MODULES)), +$(eval DRIVER_LDINFO += $(SRC_DIR)/$(ldobj).$($2_AROBJ)) +$(eval DRIVER_LDINFO_D += $(SRC_DIR)/.$($2_DBG)/$(ldobj).$($2_AROBJ)), +$(info Resolving static dependencies for '$(ldobj:%=lib%)'.) +$(if $($(ldobj)_INIT),,$(call LANG_LIB_INIT,$2,$(ldobj),$1)) +$(foreach deplib,$($(ldobj)_DEPS) $(ldobj), +$(eval DRIVER_LDINFO += $(LIB_DIR)/$(deplib).$($2_AROBJ)) +$(eval DRIVER_LDINFO_D += $(LIB_DIR)/.$($2_DBG)/$(deplib).$($2_AROBJ))) +)) +) +$(eval DRIVER_LDINFO += $(1:%.$2=%.$($2_OBJ))) +$(eval DRIVER_LDINFO_D += $(1:$(dir $1)%.$2=$(dir $1).$($2_DBG)/%.$($2_OBJ))) +$(info DRIVER_INFO: $(DRIVER_LDINFO)) +$(info DRIVER_INFO:: $(DRIVER_LDINFO_D)) # Directory setup -$(eval DRIVER_TARG_DIR := $(dir $(1:$(SRC_DIR)/%.$2=$(ROOT_DIR)/%))) -$(eval MAKE_DIRS += $(DRIVER_TARG_DIR)) -$(if $($2_DBG),$(eval MAKE_DIRS += $(DRIVER_TARG_DIR).$($2_DBG))) - -# Setup the sources for this object. A driver build rule does not include any -# compile steps at all, and so should not contain any sources that are, -# themselves, traditional "source files" like a language-compiled 'c' file. The -# driver depends on the existence of its equivalent object file (created through -# compilation), which is expected to contain a 'main' function (or entry for -# '_start'). This driver object is then simply linked to its libraries and -# module archives to create an executable binary in the output folder. -# ORDER MATTERS HERE, this is for the linker: -$(eval DRIVER_SRC := $(DRIVER_LFLAGS) $(DRIVER_DEPS)) -$(eval DRIVER_DBGSRC := $(DRIVER_LFLAGS) $(DRIVER_DBGDEPS)) -# Iterate through the list of libraries in our language and stack commands from -# left to right in the "sources" section of the LD command (or LD section of the -# commandline for the compiler), to preserve ordering and also ensure that it is -# linked correctly IN THAT ORDER (static vs dynamic). -$(foreach lib,$($2_LIBS),\ -$(if $(findstring $(lib),$(STLIBS)), -# Evaluate static lib $(lib) and add it to the dependencies and sources of the rules we built -$(eval STATIC_SRC := $(LIB_DIR)/lib$(lib).$($2_AROBJ))\ -$(eval STATIC_DBGSRC := $(LIB_DIR)/.$($2_DBG)/lib$(lib).$($2_AROBJ))\ -$(eval DRIVER_SRC := $(STATIC_SRC) $(DRIVER_SRC))\ -$(eval DRIVER_DBGSRC := $(STATIC_DBGSRC) $(DRIVER_DBGSRC))\ -$(eval DRIVER_DEPS += $(STATIC_SRC))\ -$(eval DRIVER_DBGDEPS += $(STATIC_DBGSRC)), -# Add dynamic lib to the sources with a link flag, in its correct ordering -$(eval DRIVER_SRC := -l$(lib) $(DRIVER_SRC))\ -$(eval DRIVER_DBGSRC := -l$(lib) $(DRIVER_DBGSRC))\ -)) +$(eval MAKE_DIRS += $(dir $(DRIVER_TARG))) +$(if $($2_DBG), +$(eval MAKE_DIRS += $(dir $(DRIVER_TARG_D)))) # Add the driver target to this language's targets for cleaning -$(eval SCRUB_TARGETS += $(DRIVER_TARG)) -$(DRIVER_TARG): $(DRIVER_DEPS) | $(DRIVER_TARG_DIR) - $($2_C) $($2_FLAGS) $(DRIVER_SRC) -o $$@ +$(eval SCRUB_TARGETS += $(DRIVER_TARG) $(DRIVER_TARG_D)) +$(DRIVER_TARG): $(filter-out -l%,$(DRIVER_LDINFO)) | $(dir $(DRIVER_TARG)) + $($2_C) $($2_FLAGS) $(DRIVER_LDINFO) -o $$@ # Output a rule for building with debug flags -$(eval DRIVER_DBGTARG := $(DRIVER_TARG_DIR)$(basename $(notdir $(DRIVER_TARG)))-d$($2_OUT)) -$(eval SCRUB_TARGETS += $(DRIVER_DBGTARG)) $(eval MAKE_DIRS += $(DRIVER_TARG_DIR).$($2_DBG)/) -$(DRIVER_DBGTARG): $(DRIVER_DBGDEPS) | $(DRIVER_TARG_DIR) - $($2_C) $($2_FLAGS) $(DRIVER_DBGSRC) -o $$@ +$(DRIVER_TARG_D): $(filter-out -l%,$(DRIVER_LDINFO_D)) | $(dir $(DRIVER_TARG_D)) + $($2_C) $($2_FLAGS) $(DRIVER_LDINFO_D) -o $$@ # Make a rule to run this driver after building $(DRIVER_NAME)-run: $(DRIVER_TARG) $(DRIVER_TARG) -$(DRIVER_NAME)-d: $(DRIVER_DBGTARG) +$(DRIVER_NAME)-d: $(DRIVER_TARG_D) #/SRC_LANG_DRVRULE############################################################### endef @@ -283,7 +285,10 @@ $(error No $2.mk for lib$2 and '$($1_C)' is not configured for linking)))\ # Add dependencies we found (potentially recursively, ignore repeats until later # so we can preserve ordering information for interdependency build ordering) $(if $(LIBDEPS),\ -$(eval $1_LIBS += $(LIBDEPS))) +$(eval $1_LIBS += $(LIBDEPS))\ +$(if $3,$(eval $3_DEPS += $(LIBDEPS)))\ +$(eval $2_DEPS += $(LIBDEPS))\ +) # languages that can link this library (typically any lang that shares the # object format (ELF by default, but this is compiler-dependent (e.g. emcc uses # llvm bitcode, which is just an intermediary representation of data that can @@ -302,6 +307,8 @@ $(eval BUILTLIBS += $2)) # Recurse this function for every libdep encountered $(foreach libdep,$(LIBDEPS),\ $(call LANG_LIB_INIT,$1,$(libdep),$2)) +$(eval $2_DEPS := $(shell echo "$($2_DEPS)" | $(call AWK_REVERSE_SQUASH))) +$(eval $2_INIT := t) #/LANG_LIB_INIT################################################################# endef @@ -344,15 +351,5 @@ $(module)_TRG += $($(module)_$1_TRG) $(foreach src,$(filter $(SRC_DIR)/$(module)/%,$($1_MOD_SRC)),\ $(eval $(call SRC_LANG_RULE,$(src),$1))\ )) -# For all the listed libraries, initialize the library, which will set up all of -# its local ($1_LIBS, etc) data -$(foreach lib,$($1_LIBS),\ -$(eval $(call LANG_LIB_INIT,$1,$(lib),$1))) -# The initializer produces an ordered list of interlinked dependencies in groups -# by depth, so when reading backwards and compressing repeats we are left with a -# reliable build order for library interlinking. this awk program just looks -# through a list of space separated words backwards failing to print when it -# encounters a repeat -$1_LIBS := $(shell echo "$($1_LIBS)" | $(call AWK_REVERSE_SQUASH)) #/LANG_INIT###################################################################### endef -- 2.18.0