diff --git a/configure/RULES.ioc b/configure/RULES.ioc index 1024fcb22..da314a406 100644 --- a/configure/RULES.ioc +++ b/configure/RULES.ioc @@ -24,11 +24,15 @@ else clean$(DIVIDER)$(ARCH) clean: endif -cdCommands envPaths dllPath.bat relPaths.sh: \ +cdCommands dllPath.bat relPaths.sh: \ $(wildcard $(TOP)/configure/RELEASE*) \ - $(wildcard $(TOP)/configure/CONFIG_SITE*) $(INSTALL_BIN) + $(wildcard $(TOP)/configure/CONFIG_SITE*) | $(INSTALL_BIN) $(CONVERTRELEASE) -a $(ARCH) -t $(IOCS_APPL_TOP) $@ +envPaths: $(wildcard $(TOP)/configure/RELEASE*) \ + $(wildcard $(TOP)/configure/CONFIG_SITE*) | $(INSTALL_BIN) + $(CONVERTRELEASE) -t $(IOCS_APPL_TOP) $@ + realclean: $(RM) cdCommands envPaths dllPath.bat relPaths.sh diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 31a6674ff..7f4c62e90 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -15,6 +15,19 @@

Changes made on the 3.15 branch since 3.15.3

+

IOC environment variables and build parameters

+ +

The IOC now sets a number of environment variables at startup that provide +the version of EPICS Base it was built against (EPICS_VERSION_...) and its build +architecture (ARCH). In some cases this allows a single iocBoot/ioc directory to +be used to run the same IOC on several different architectures without any +changes.

+ +

There are also 3 new environment parameters (EPICS_BUILD_...) available that +C/C++ code can use to find out the target architecture, OS class and compiler +class it was built with. These may be useful when writing interfaces to other +languages.

+

New implementation of promptgroup/gui_group field property

The mechanism behind the "promptgroup()" field property inside a record type diff --git a/src/ioc/misc/iocshRegisterCommon.c b/src/ioc/misc/iocshRegisterCommon.c index 0341dfbd6..f5f339f46 100644 --- a/src/ioc/misc/iocshRegisterCommon.c +++ b/src/ioc/misc/iocshRegisterCommon.c @@ -7,6 +7,8 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ +#include "envDefs.h" +#include "epicsVersion.h" #include "iocsh.h" #include "libComRegister.h" @@ -21,9 +23,28 @@ #include "registryIocRegister.h" #include "rsrvIocRegister.h" +#define quote(v) #v +#define str(v) quote(v) + void iocshRegisterCommon(void) { iocshPpdbbase = &pdbbase; + const char *targetArch = envGetConfigParamPtr(&EPICS_BUILD_TARGET_ARCH); + + /* This uses a config param so the user can override it */ + if (targetArch) { + epicsEnvSet("ARCH", targetArch); + } + + /* Base build version variables */ + epicsEnvSet("EPICS_VERSION_MAJOR", str(EPICS_VERSION)); + epicsEnvSet("EPICS_VERSION_MIDDLE", str(EPICS_REVISION)); + epicsEnvSet("EPICS_VERSION_MINOR", str(EPICS_MODIFICATION)); + epicsEnvSet("EPICS_VERSION_PATCH", str(EPICS_PATCH_LEVEL)); + epicsEnvSet("EPICS_VERSION_SNAPSHOT", EPICS_DEV_SNAPSHOT); + epicsEnvSet("EPICS_VERSION_SITE", EPICS_SITE_VERSION); + epicsEnvSet("EPICS_VERSION_SHORT", EPICS_VERSION_SHORT); + epicsEnvSet("EPICS_VERSION_FULL", EPICS_VERSION_FULL); dbStaticIocRegister(); registryIocRegister(); diff --git a/src/libCom/env/RULES b/src/libCom/env/RULES index f63475d25..07f71a5a0 100644 --- a/src/libCom/env/RULES +++ b/src/libCom/env/RULES @@ -8,5 +8,7 @@ # This is a Makefile fragment, see src/libCom/Makefile. envData.c: $(LIBCOM)/env/envDefs.h $(LIBCOM)/env/bldEnvData.pl \ - $(CONFIG)/CONFIG_ENV $(CONFIG)/CONFIG_SITE_ENV - $(PERL) $(LIBCOM)/env/bldEnvData.pl $(INSTALL_QUIETLY) $(CONFIG) + $(CONFIG)/CONFIG_ENV $(CONFIG)/CONFIG_SITE_ENV \ + $(wildcard $(CONFIG)/os/CONFIG_SITE_ENV.$(T_A)) + $(PERL) $(LIBCOM)/env/bldEnvData.pl $(INSTALL_QUIETLY) -t $(T_A) \ + -c $(CMPLR_CLASS) -s $(OS_CLASS) $(CONFIG) diff --git a/src/libCom/env/bldEnvData.pl b/src/libCom/env/bldEnvData.pl index 993c36cee..a23907dc8 100644 --- a/src/libCom/env/bldEnvData.pl +++ b/src/libCom/env/bldEnvData.pl @@ -26,13 +26,13 @@ use Text::Wrap; my $tool = basename($0); -our ($opt_h, $opt_q); +our ($opt_h, $opt_q, $opt_t, $opt_s, $opt_c); our $opt_o = 'envData.c'; $Getopt::Std::OUTPUT_HELP_VERSION = 1; $Text::Wrap::columns = 75; -&HELP_MESSAGE unless getopts('ho:q') && @ARGV == 1; +&HELP_MESSAGE unless getopts('ho:qt:s:c:') && @ARGV == 1; &HELP_MESSAGE if $opt_h; my $config = AbsPath(shift); @@ -52,16 +52,31 @@ while () { } close SRC; -# Read the values from the CONFIG_ENV and CONFIG_SITE_ENV files +# A list of configure/CONFIG_* files to read # -my $config_env = "$config/CONFIG_ENV"; -my $config_site_env = "$config/CONFIG_SITE_ENV"; +my @configs = ("$config/CONFIG_ENV", "$config/CONFIG_SITE_ENV"); -my %values; -readReleaseFiles($config_env, \%values); -readReleaseFiles($config_site_env, \%values); +if ($opt_t) { + my $config_arch_env = "$config/os/CONFIG_SITE_ENV.$opt_t"; + push @configs, $config_arch_env + if -f $config_arch_env; +} -# Warn about any vars with no value +my @sources = ($env_defs, @configs); + +# Get values from the config files +# +my (%values, @dummy); +readRelease($_, \%values, \@dummy) foreach @configs; +expandRelease(\%values); + +# Get values from the command-line +# +$values{EPICS_BUILD_COMPILER_CLASS} = $opt_c if $opt_c; +$values{EPICS_BUILD_OS_CLASS} = $opt_s if $opt_s; +$values{EPICS_BUILD_TARGET_ARCH} = $opt_t if $opt_t; + +# Warn about vars with no configured value # my @undefs = grep {!exists $values{$_}} @vars; warn "$tool: No value given for $_\n" foreach @undefs; @@ -73,13 +88,13 @@ print "Generating $opt_o\n" unless $opt_q; open OUT, '>', $opt_o or die "$tool: Cannot create $opt_o: $!\n"; +my $sources = join "\n", map {" * $_"} @sources; + print OUT << "END"; /* Generated file $opt_o * * Created from - * $env_defs - * $config_env - * $config_site_env +$sources */ #include @@ -88,18 +103,23 @@ print OUT << "END"; END -# Define all parameters, giving variable name and default value +# Define a default value for each named parameter # foreach my $var (@vars) { - my $default = $values{$var} || ''; - $default =~ s/^"//; - $default =~ s/"$//; + my $default = $values{$var}; + if (defined $default) { + $default =~ s/^"//; + $default =~ s/"$//; + } + else { + $default = ''; + } print OUT "epicsShareDef const ENV_PARAM $var =\n", " {\"$var\", \"$default\"};\n"; } -# Now create a list of all those parameters +# Also provide a list of all defined parameters # print OUT "\n", "epicsShareDef const ENV_PARAM* env_param_list[] = {\n", @@ -112,6 +132,9 @@ sub HELP_MESSAGE { " -h Help: Print this message\n", " -q Quiet: Only print errors\n", " -o file Output filename, default is $opt_o\n", + " -t arch Target architecture \$(T_A) name\n", + " -s os Operating system \$(OS_CLASS)\n", + " -c comp Compiler class \$(CMPLR_CLASS)\n", "\n"; exit 1; diff --git a/src/libCom/env/envDefs.h b/src/libCom/env/envDefs.h index dfa911115..437e688e3 100644 --- a/src/libCom/env/envDefs.h +++ b/src/libCom/env/envDefs.h @@ -40,7 +40,7 @@ typedef struct envParam { } ENV_PARAM; /* - * bldEnvData looks for "epicsShareExtern const ENV_PARAM" + * bldEnvData.pl looks for "epicsShareExtern const ENV_PARAM ;" */ epicsShareExtern const ENV_PARAM EPICS_CA_ADDR_LIST; epicsShareExtern const ENV_PARAM EPICS_CA_CONN_TMO; @@ -58,6 +58,9 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_SERVER_PORT; epicsShareExtern const ENV_PARAM EPICS_CA_BEACON_PERIOD; /* deprecated */ epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PERIOD; epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT; +epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS; +epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS; +epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH; epicsShareExtern const ENV_PARAM EPICS_TIMEZONE; epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET; epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT; diff --git a/src/libCom/misc/makeEpicsVersion.pl b/src/libCom/misc/makeEpicsVersion.pl index 2a720e86d..f7f134f87 100644 --- a/src/libCom/misc/makeEpicsVersion.pl +++ b/src/libCom/misc/makeEpicsVersion.pl @@ -47,8 +47,11 @@ map { die "$tool: Variable missing from $infile" unless defined $_; } $ver, $rev, $mod, $patch, $snapshot, $commit_date; +$commit_date =~ s/^\$\$Date$\$$/\1/; + my $ver_str = "$ver.$rev.$mod"; $ver_str .= ".$patch" if $patch > 0; +my $ver_short = $ver_str; $ver_str .= $snapshot if $snapshot ne ''; $ver_str .= "-$opt_v" if $opt_v; @@ -71,10 +74,15 @@ print $OUT <<"END"; #define EPICS_PATCH_LEVEL $patch #define EPICS_DEV_SNAPSHOT "$snapshot" #define EPICS_SITE_VERSION "$opt_v" + +#define EPICS_VERSION_SHORT "$ver_short" +#define EPICS_VERSION_FULL "$ver_str" #define EPICS_VERSION_STRING "EPICS $ver_str" #define epicsReleaseVersion "EPICS R$ver_str $commit_date" -#define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P)) +#ifndef VERSION_INT +# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P)) +#endif #define EPICS_VERSION_INT VERSION_INT($ver, $rev, $mod, $patch) #endif /* INC_${obase}_H */ diff --git a/src/template/base/top/exampleBoot/ioc/Makefile@Common b/src/template/base/top/exampleBoot/ioc/Makefile@Common index 64a3e8bf7..e064d7344 100644 --- a/src/template/base/top/exampleBoot/ioc/Makefile@Common +++ b/src/template/base/top/exampleBoot/ioc/Makefile@Common @@ -1,5 +1,4 @@ TOP = ../.. include $(TOP)/configure/CONFIG -ARCH = _ARCH_ TARGETS = envPaths include $(TOP)/configure/RULES.ioc diff --git a/src/template/base/top/iocBoot/ioc/Makefile@Common b/src/template/base/top/iocBoot/ioc/Makefile@Common index 64a3e8bf7..e064d7344 100644 --- a/src/template/base/top/iocBoot/ioc/Makefile@Common +++ b/src/template/base/top/iocBoot/ioc/Makefile@Common @@ -1,5 +1,4 @@ TOP = ../.. include $(TOP)/configure/CONFIG -ARCH = _ARCH_ TARGETS = envPaths include $(TOP)/configure/RULES.ioc diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl index abf63c3ec..70f38ed57 100644 --- a/src/tools/convertRelease.pl +++ b/src/tools/convertRelease.pl @@ -75,7 +75,7 @@ my @apps = ('TOP'); # Records the order of definitions in RELEASE file my $relfile = "$top/configure/RELEASE"; die "Can't find $relfile" unless (-f $relfile); readReleaseFiles($relfile, \%macros, \@apps, $arch); -expandRelease(\%macros, \@apps); +expandRelease(\%macros); # This is a perl switch statement: @@ -134,6 +134,7 @@ sub relPaths { } sub binDirs { + die "Architecture not set (use -a option)\n" unless ($arch); my @includes = grep !m/^ (RULES | TEMPLATE_TOP) $/x, @apps; my @path; foreach my $app (@includes) { @@ -165,7 +166,6 @@ sub cdCommands { my $ioc = $cwd; $ioc =~ s/^.*\///; # iocname is last component of directory name - print OUT "putenv(\"ARCH=$arch\")\n"; print OUT "putenv(\"IOC=$ioc\")\n"; foreach my $app (@includes) { @@ -188,7 +188,6 @@ sub cdCommands { # Include parentheses anyway in case CEXP users want to use this. # sub envPaths { - die "Architecture not set (use -a option)" unless ($arch); my @includes = grep !m/^ (RULES | TEMPLATE_TOP) $/x, @apps; unlink($outfile); @@ -197,7 +196,6 @@ sub envPaths { my $ioc = $cwd; $ioc =~ s/^.*\///; # iocname is last component of directory name - print OUT "epicsEnvSet(\"ARCH\",\"$arch\")\n"; print OUT "epicsEnvSet(\"IOC\",\"$ioc\")\n"; foreach my $app (@includes) { @@ -223,7 +221,7 @@ sub checkRelease { my @order = (); my $relfile = "$path/configure/RELEASE"; readReleaseFiles($relfile, \%check, \@order, $arch); - expandRelease(\%check, \@order); + expandRelease(\%check); delete $check{TOP}; delete $check{EPICS_HOST_ARCH};