From 23a9e8bea6e4df3445a3aee4700cc07c28b99028 Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Fri, 2 Nov 2018 13:44:40 +0100 Subject: [PATCH] support for exact version number match --- App/tools/driver.makefile | 88 +++++++++++++++++++++------------------ require.c | 63 ++++++++++++++++------------ 2 files changed, 83 insertions(+), 68 deletions(-) diff --git a/App/tools/driver.makefile b/App/tools/driver.makefile index 2bd3d02..b1acff3 100644 --- a/App/tools/driver.makefile +++ b/App/tools/driver.makefile @@ -428,7 +428,7 @@ install build:: # Loop over all architectures. install build debug:: @+for ARCH in ${CROSS_COMPILER_TARGET_ARCHS}; do \ - umask 002; echo MAKING ARCH $$ARCH; ${MAKE} -f ${USERMAKEFILE} T_A=$$ARCH $@; \ + umask 002; echo MAKING ${EPICSVERSION} ARCH $$ARCH; ${MAKE} -f ${USERMAKEFILE} T_A=$$ARCH $@; \ done else # T_A @@ -438,29 +438,6 @@ ifeq ($(filter O.%,$(notdir ${CURDIR})),) # Target architecture defined. # Still in source directory, third run. -# Add include directory of other modules to include file search path. -# By default use highest version of all other modules installed for -# current EPICSVERSION and T_A. -# The user can overwrite by defining _VERSION=. -# This version can be incomplete (only or .). -# In this case the hightest matching full version (..) -# will be selected. - -# The tricky part is to sort versions numerically. -# Make can't but ls -v can. -# Only accept numerical versions (needs extended glob). -# This is slow, thus do it only once for each EPICSVERSION. - -define ADD_OTHER_MODULE_INCLUDES -$(eval $(1)_VERSION := $(patsubst ${EPICS_MODULES}/$(1)/%/R${EPICSVERSION}/lib/$(T_A)/../../include,%,$(firstword $(shell ls -dvr ${EPICS_MODULES}/$(1)/+([0-9]).+([0-9]).+([0-9])/R${EPICSVERSION}/lib/$(T_A)/../../include 2>/dev/null)))) -export $(1)_VERSION -OTHER_MODULE_INCLUDES += $$(addprefix -I,$$(firstword $$(shell ls -dvr ${EPICS_MODULES}/$(1)/$$($(1)_VERSION)*(.+([0-9]))/R${EPICSVERSION}/include 2>/dev/null))) -endef -$(eval $(foreach m,$(filter-out $(PRJ) $(IGNORE_MODULES),$(notdir $(wildcard ${EPICS_MODULES}/*))),$(call ADD_OTHER_MODULE_INCLUDES,$m))) -# Include path for old style modules. -OTHER_MODULE_INCLUDES += $(addprefix -I,$(wildcard ${INSTBASE}/iocBoot/R${EPICSVERSION}/include)) -export OTHER_MODULE_INCLUDES - ifeq ($(filter ${OS_CLASS},${OS_CLASS_LIST}),) install% build%: build @@ -479,6 +456,36 @@ install build: else +# Add include directory of other modules to include file search path. +# By default use highest version of all other modules installed for +# current EPICSVERSION and T_A. +# The user can overwrite by defining _VERSION=. +# This version can be incomplete (only or .). +# In this case the hightest matching full version (..) +# will be selected. + +# The tricky part is to sort versions numerically. +# Make can't but ls -v can. +# Only accept numerical versions (needs extended glob). +# This is slow, thus do it only once for each EPICSVERSION. + +define ADD_OTHER_MODULE_INCLUDES +$(eval $(1)_VERSION = $(patsubst ${EPICS_MODULES}/$(1)/%/R${EPICSVERSION}/lib/$(T_A)/../../include,%,$(firstword $(shell ls -dvr ${EPICS_MODULES}/$(1)/+([0-9]).+([0-9]).+([0-9])/R${EPICSVERSION}/lib/$(T_A)/../../include 2>/dev/null)))) +export $(1)_VERSION +OTHER_MODULE_INCLUDES += $$(addprefix -I,$$(firstword $$(shell ls -dvr ${EPICS_MODULES}/$(1)/$$($(1)_VERSION)*(.+([0-9]))/R${EPICSVERSION}/include 2>/dev/null))) +endef +$(eval $(foreach m,$(filter-out $(PRJ) $(IGNORE_MODULES),$(notdir $(wildcard ${EPICS_MODULES}/*))),$(call ADD_OTHER_MODULE_INCLUDES,$m))) +# Include path for old style modules. +OLD_INCLUDE = $(wildcard ${INSTBASE}/iocBoot/R${EPICSVERSION}/include) +OTHER_MODULE_INCLUDES += $(addprefix -I,$(OLD_INCLUDE)) +export OTHER_MODULE_INCLUDES + +# Manually required modules. +define ADD_MANUAL_DEPENDENCIES +$(eval $(1)_VERSION = $(or $(patsubst ${EPICS_MODULES}/$(1)/%/R${EPICSVERSION},%,$(firstword $(shell ls -dvr ${EPICS_MODULES}/$(1)/+([0-9]).+([0-9]).+([0-9])/R${EPICSVERSION} 2>/dev/null))),$(basename $(lastword $(subst -, ,$(basename $(realpath ${INSTBASE}/iocBoot/R${EPICSVERSION}/${T_A}/$(1).dep))))))) +endef +$(eval $(foreach m,${REQ},$(call ADD_MANUAL_DEPENDENCIES,$m))) + O.%: $(MKDIR) $@ @@ -520,7 +527,8 @@ export CFG export IGNORE_MODULES -export API_MAY_CHANGE_BETWEEN_MINOR_VERSIONS +export USE_EXACT_VERSION += $(ABI_MAY_CHANGE) +export USE_EXACT_MINOR_VERSION += $(ABI_MAY_CHANGE_BETWEEN_MINOR_VERSIONS) else # in O.* ## RUN 4 @@ -537,15 +545,9 @@ COMMON_DIR = ${COMMON_DIR_${EPICS_BASETYPE}} # Remove include directory for this module from search path. # 3.13 and 3.14+ use different variables -INSTALL_INCLUDES := $(strip $(OTHER_MODULE_INCLUDES)) +INSTALL_INCLUDES = $(strip $(OTHER_MODULE_INCLUDES)) EPICS_INCLUDES = -# Manually required modules. -define ADD_MANUAL_DEPENDENCIES -$(eval $(1)_VERSION := $(or $(patsubst ${EPICS_MODULES}/$(1)/%/R${EPICSVERSION},%,$(firstword $(shell ls -dvr ${EPICS_MODULES}/$(1)/+([0-9]).+([0-9]).+([0-9])/R${EPICSVERSION} 2>/dev/null))),$(basename $(lastword $(subst -, ,$(basename $(realpath ${INSTBASE}/iocBoot/R${EPICSVERSION}/${T_A}/$(1).dep))))))) -endef -$(eval $(foreach m,${REQ},$(call ADD_MANUAL_DEPENDENCIES,$m))) - # EPICS 3.13 uses :: in some rules where 3.14 uses : ifeq (${EPICS_BASETYPE},3.13) INSTALLRULE=install:: @@ -663,6 +665,7 @@ endif endif # Both, 3.13 and 3.14+ from here. +ifndef USE_EXACT_VERSION # For backward compatibility: # Provide a global symbol for every version with the same # major and equal or smaller minor version number. @@ -674,7 +677,7 @@ MAJOR=$(word 1,${MAJOR_MINOR_PATCH}) MINOR=$(word 2,${MAJOR_MINOR_PATCH}) PATCH=$(word 3,${MAJOR_MINOR_PATCH}) ifneq (${MINOR},) -ifdef API_MAY_CHANGE_BETWEEN_MINOR_VERSIONS +ifdef USE_EXACT_MINOR_VERSION ALLMINORS = ${MINOR} else ALLMINORS := $(shell for ((i=0;i<=${MINOR};i++));do echo $$i;done) @@ -687,6 +690,7 @@ PROVIDES = ${ALLMINORS:%=-Wl,--defsym,${PRJ}Lib_${MAJOR}.%=0} endif # Linux endif # MINOR LDFLAGS += ${PROVIDES} ${USR_LDFLAGS_${T_A}} +endif # !USE_EXACT_VERSION # Create and include dependency files. # 3.13 does not make those files at all. @@ -864,11 +868,17 @@ debug:: INSTALLS += ${INSTALL_CFGS} ${INSTALL_SCRS} ${INSTALL_HDRS} ${INSTALL_DBDS} ${INSTALL_DBS} ${INSTALL_LIBS} ${INSTALL_BINS} ${INSTALL_DEPS} -ifdef API_MAY_CHANGE_BETWEEN_MINOR_VERSIONS +ifdef USE_EXACT_VERSION +INSTALLS += ${EPICS_MODULES}/${PRJ}/use_exact_version +%/use_exact_version: + touch $@ +else +ifdef USE_EXACT_MINOR_VERSION INSTALLS += ${EPICS_MODULES}/${PRJ}/use_exact_minor_version %/use_exact_minor_version: touch $@ endif +endif ${INSTALLRULE} ${INSTALLS} @@ -1048,15 +1058,11 @@ ${DEPFILE}: ${LIBOBJS} $(USERMAKEFILE) @echo "Collecting dependencies" $(RM) $@ @echo "# Generated file. Do not edit." > $@ - # Check dependencies on other module headers. - cat *.d 2>/dev/null | sed 's/ /\n/g' | sed -n 's%${EPICS_MODULES}/*\([^/]*\)/\([0-9]*\.[0-9]*\)\.[0-9]*/.*%\1 \2%p;s%$(EPICS_MODULES)/*\([^/]*\)/\([^/]*\)/.*%\1 \2%p'| sort -u >> $@ -ifneq ($(strip ${REQ}),) - # Manully added dependencies: ${REQ} - @$(foreach m,${REQ},echo "$m $(or ${$m_VERSION},$(and $(wildcard ${EPICS_MODULES}/$m),$(error REQUIRED module $m has no numbered version. Set $m_VERSION)),$(warning REQUIRED module $m not found for ${T_A}.))" >> $@;) -endif +# Check dependencies on ${REQ} and other module headers. + $(foreach m,$(sort ${REQ} $(shell cat *.d 2>/dev/null | sed 's/ /\n/g' | sed -n 's%${EPICS_MODULES}/*\([^/]*\)/.*%\1%p' | sort -u)),echo "$m $(or $(if $(wildcard ${EPICS_MODULES}/$m/use_exact_version),${$m_VERSION},$(basename ${$m_VERSION})),$(and $(wildcard ${EPICS_MODULES}/$m),$(error REQUIRED module $m has no numbered version. Set $m_VERSION)),$(warning REQUIRED module $m not found for ${T_A}.))" >> $@;) ifdef OLD_INCLUDE # Check dependencies on old style driver headers. - @${MAKEHOME}/getPrerequisites.tcl -dep ${OLD_INCLUDE} | grep -vw -e ${PRJ} -e ^$$ >> $@ && echo "Warning: dependency on old style driver"; true; + ${MAKEHOME}/getPrerequisites.tcl -dep ${OLD_INCLUDE} | grep -vw -e ${PRJ} -e ^$$ >> $@ && echo "Warning: dependency on old style driver"; true; endif # Remove MakefileInclude after we are done because it interfers with our way to build. diff --git a/require.c b/require.c index 191f95b..d13b5bc 100644 --- a/require.c +++ b/require.c @@ -874,7 +874,7 @@ int libversionShow(const char* outfile) #define TESTVERS 2 #define HIGHER 3 -static int compareVersions(const char* found, const char* request, int exactMinorNeeded) +static int compareVersions(const char* found, const char* request, int exactnessLevel) { int found_major, found_minor=0, found_patch=0, found_parts = 0; int req_major, req_minor, req_patch, req_parts; @@ -883,7 +883,7 @@ static int compareVersions(const char* found, const char* request, int exactMino int n; if (requireDebug) - printf("require: compareVersions(found=%s, request=%s, exactMinorNeeded=%d)\n", found, request, exactMinorNeeded); + printf("require: compareVersions(found=%s, request=%s, exactnessLevel=%d)\n", found, request, exactnessLevel); if (found == NULL || found[0] == 0) /* no version found: any requested? */ { @@ -974,7 +974,7 @@ static int compareVersions(const char* found, const char* request, int exactMino } if (found_minor > req_minor) /* minor larger than required */ { - if (req_extra[0] == '+' && !exactMinorNeeded) + if (req_extra[0] == '+' && exactnessLevel == 0) { if (requireDebug) printf("require: compareVersions: MATCH minor number higher than requested with +\n"); @@ -1005,7 +1005,7 @@ static int compareVersions(const char* found, const char* request, int exactMino printf("require: compareVersions: MATCH patch level matches exactly requested\n"); return MATCH; } - if (req_extra[0] == '+') + if (req_extra[0] == '+' && exactnessLevel <= 1) { if (requireDebug) printf("require: compareVersions: MATCH patch level higher than requested with +\n"); @@ -1131,7 +1131,7 @@ static off_t fileSize(const char* filename) { case S_IFREG: if (requireDebug) - printf("require: file %s exists, size %lld bytes\n", + printf("require: file %s exists, size %llu bytes\n", filename, (unsigned long long)filestat.st_size); return filestat.st_size; case S_IFDIR: @@ -1247,7 +1247,7 @@ static int require_priv(const char* module, const char* version, const char* arg char* symbolname; char filename[PATH_MAX]; - int exactMinorNeeded = 0; + int exactnessLevel = 0; int someVersionFound = 0; int someArchFound = 0; @@ -1301,11 +1301,19 @@ static int require_priv(const char* module, const char* version, const char* arg dirname = getLibLocation(module); if (requireDebug && dirname[0]) printf("require: library found in %s\n", dirname); - snprintf(filename, sizeof(filename), "%s%n.." OSI_PATH_SEPARATOR ".." OSI_PATH_SEPARATOR "use_exact_minor_version", + snprintf(filename, sizeof(filename), "%s%n.." OSI_PATH_SEPARATOR ".." OSI_PATH_SEPARATOR "use_exact_version", dirname, &releasediroffs); if (fileExists(filename)) - exactMinorNeeded = 1; - switch (compareVersions(loaded, version, exactMinorNeeded)) + { + exactnessLevel = 2; + } + else + { + snprintf(filename+releasediroffs, sizeof(filename)-releasediroffs, ".." OSI_PATH_SEPARATOR ".." OSI_PATH_SEPARATOR "use_exact_minor_version"); + if (fileExists(filename)) + exactnessLevel = 1; + } + switch (compareVersions(loaded, version, exactnessLevel)) { case TESTVERS: if (version) @@ -1320,7 +1328,8 @@ static int require_priv(const char* module, const char* version, const char* arg int i = strlen(version); if (version[i-1] == '+') i--; printf("Conflict between required %s%s version %.*s and already loaded version %s.\n", - exactMinorNeeded ? "exact " : "" , module, i, version, loaded); + exactnessLevel > 1 ? "exact " : exactnessLevel > 0 ? "exact minor " : "" , + module, i, version, loaded); return -1; } } @@ -1347,25 +1356,25 @@ static int require_priv(const char* module, const char* version, const char* arg end = strchr(end+2, OSI_PATH_LIST_SEPARATOR[0]); if (end) dirlen = (int)(end++ - dirname); else dirlen = (int)strlen(dirname); - if (dirlen == 0) continue; /* ignore empty driverpath elements */ - if (requireDebug) - printf("require: trying %.*s\n", dirlen, dirname); + if (dirlen == 0) + continue; /* ignore empty driverpath elements */ + + if (!TRY_FILE(0, "%.*s" OSI_PATH_SEPARATOR, dirlen, dirname)) + continue; /* ignore non-existing driverpath elements */ - snprintf(filename, sizeof(filename), "%.*s" OSI_PATH_SEPARATOR "%s" OSI_PATH_SEPARATOR "%n" OSI_PATH_SEPARATOR "use_exact_minor_version", - dirlen, dirname, module, &modulediroffs); dirlen += strlen(OSI_PATH_SEPARATOR); - /* filename = "/[dirlen]/[modulediroffs]/use_exact_minor_version" */ - - if (fileExists(filename)) - exactMinorNeeded = 1; + /* filename = "/[dirlen]" */ + + snprintf(filename+dirlen, sizeof(filename)-dirlen, "%s" OSI_PATH_SEPARATOR "%n", module, &modulediroffs); + modulediroffs += dirlen; + /* filename = "/[dirlen]/[modulediroffs]" */ /* Does the module directory exist? */ - filename[modulediroffs] = 0; IF_OPEN_DIR(filename) { - if (requireDebug) - printf("require: found directory %s\n", filename); + if (TRY_FILE(modulediroffs, "use_exact_version")) exactnessLevel = 2; + else if (TRY_FILE(modulediroffs, "use_exact_minor_version")) exactnessLevel = 1; /* Now look for versions. */ START_DIR_LOOP @@ -1379,10 +1388,10 @@ static int require_priv(const char* module, const char* version, const char* arg /* Look for highest matching version. */ if (requireDebug) - printf("require: checking version %s against required %s\n", + printf("require: comparing found version %s against required %s\n", currentFilename, version); - switch ((status = compareVersions(currentFilename, version, exactMinorNeeded))) + switch ((status = compareVersions(currentFilename, version, exactnessLevel))) { case EXACT: /* exact match found */ case MATCH: /* all given numbers match. */ @@ -1418,10 +1427,10 @@ static int require_priv(const char* module, const char* version, const char* arg } /* Is it higher than the one we found before? */ - if (found && requireDebug) + if (requireDebug) printf("require: %s %s support for %s %s found, compare against previously found %s\n", module, currentFilename, epicsRelease, targetArch, found); - if (!found || compareVersions(currentFilename, found, exactMinorNeeded) == HIGHER) + if (!found || compareVersions(currentFilename, found, exactnessLevel) == HIGHER) { if (requireDebug) printf("require: %s %s looks promising\n", module, currentFilename); @@ -1565,7 +1574,7 @@ loadlib: /* check what we got */ if (requireDebug) printf("require: compare requested version %s with loaded version %s\n", version, found); - if (compareVersions(found, version, exactMinorNeeded) == MISMATCH) + if (compareVersions(found, version, exactnessLevel) == MISMATCH) { fprintf(stderr, "Requested %s version %s not available, found only %s.\n", module, version, found);