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};