From 3885c809a659282c334a8ca8b26a483c269f33a0 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 22 Aug 2014 15:23:51 -0400 Subject: [PATCH 01/15] introduce genVersionHeader.pl --- configure/RULES_BUILD | 13 ++++++ src/tools/Makefile | 1 + src/tools/genVersionHeader.pl | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/tools/genVersionHeader.pl diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 711da3434..0af9b6e55 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -359,6 +359,19 @@ tapfiles: $(TESTSCRIPTS) $(TAPFILES) @$(RM) $@ $(PERL) $(TOOLS)/makeTestfile.pl $@ $< +#--------------------------------------------------------------- +# Generate header with version number from VCS + +ifneq ($(VERHEADER),) +GENVERSIONHEADER ?= $(PERL) $(TOOLS)/genVersionHeader.pl +MODVERSION ?= undefined +MODMACRO ?= MODULEVERSION + +$(VERHEADER):: + $(GENVERSIONHEADER) -t $(TOP) -V $(MODVERSION) -N $(MODMACRO) $@ + +endif + #--------------------------------------------------------------- # Install rules for BIN_INSTALLS and LIB_INSTALLS diff --git a/src/tools/Makefile b/src/tools/Makefile index 496b0e4d1..ff5c55e39 100644 --- a/src/tools/Makefile +++ b/src/tools/Makefile @@ -49,6 +49,7 @@ PERL_SCRIPTS += dbdToMenuH.pl PERL_SCRIPTS += dbdToRecordtypeH.pl PERL_SCRIPTS += dbdExpand.pl PERL_SCRIPTS += dbdToHtml.pl +PERL_SCRIPTS += genVersionHeader.pl PERL_SCRIPTS += registerRecordDeviceDriver.pl include $(TOP)/configure/RULES diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl new file mode 100644 index 000000000..0fd6db2df --- /dev/null +++ b/src/tools/genVersionHeader.pl @@ -0,0 +1,74 @@ +#!/usr/bin/env perl +# +# Generate a C header file which +# defines a macro with a string +# describing the VCS revision +# + +use EPICS::Getopts; + +use strict; + +our($opt_v,$opt_t,$opt_N,$opt_V); + +$opt_N = "MODVERSION"; +$opt_V = "undefined"; +$opt_t = "."; +my $foundvcs = 0; +my $result; + +getopts("vt:N:V:") or + die "Usage: genVersionHeader.pl [-t top] [-N NAME] [-V VERSION] output.h"; + +my ($outfile) = @ARGV; + +if(-d "$opt_t/.hg") { # Mercurial + # v1-4-abcdef-dirty + # is 4 commits after tag 'v1' with short hash abcdef + # with uncommited modifications + $result = `cd "$opt_t" && hg tip --template '{latesttag}-{latesttagdistance}-{node|short}\n'`; + chomp($result); + if(length($result)>1) { + $opt_V = $result; + $foundvcs = 1; + } + # see if working copy has modifications, additions, removals, or missing files + my $hasmod = `cd "$opt_t" && hg status -m -a -r -d`; + chomp($hasmod); + if(length($hasmod)>0) { + $opt_V = "$opt_V-dirty"; + } +} +if(!$foundvcs && -d "$opt_t/.git") { + # same format as Mercurial + $result = `git --git-dir="$opt_t/.git" describe --tags --dirty`; + chomp($result); + if(length($result)>1) { + $opt_V = $result; + $foundvcs = 1; + } +} + +my $output = "#ifndef $opt_N\n# define $opt_N \"$opt_V\"\n#endif\n"; +print "== would\n$output" if $opt_v; + +my $DST; +if(open($DST, '+<', $outfile)) { + my $actual = join("", <$DST>); + print "== have\n$actual" if $opt_v; + + if($actual eq $output) { + print "keep existing $outfile\n"; + exit(0) + } + print "updating $outfile\n"; +} else { + print "create $outfile\n"; + open($DST, '>', $outfile) or die "Unable to open or create $outfile"; +} + +seek($DST,0,0); +truncate($DST,0); +print $DST $output; + +close($DST); From 55cf45364c69fc5d15d733ac24d2bc23c8641894 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 Aug 2014 11:03:54 -0700 Subject: [PATCH 02/15] tools: Make genVersionHeader.pl log more detailed and streamlined with other EPICS build output --- src/tools/genVersionHeader.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index 0fd6db2df..357c17acc 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -58,13 +58,13 @@ if(open($DST, '+<', $outfile)) { print "== have\n$actual" if $opt_v; if($actual eq $output) { - print "keep existing $outfile\n"; + print "Keeping existing VCS version header $outfile\n"; exit(0) } - print "updating $outfile\n"; + print "Updating VCS version header $outfile\n"; } else { - print "create $outfile\n"; - open($DST, '>', $outfile) or die "Unable to open or create $outfile"; + print "Creating VCS version header $outfile\n"; + open($DST, '>', $outfile) or die "Unable to open or create VCS version header $outfile"; } seek($DST,0,0); From 6a018dce35268a2ac5f9f8c337873dfd2082efe9 Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Wed, 27 Aug 2014 11:06:57 -0700 Subject: [PATCH 03/15] tools: Add support for Darcs to genVersionHeader.pl --- src/tools/genVersionHeader.pl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index 357c17acc..d4f1c52dc 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -22,6 +22,22 @@ getopts("vt:N:V:") or my ($outfile) = @ARGV; +if(-d "$opt_t/_darcs") { # Darcs + # v1-4-dirty + # is tag 'v1' plus 4 patches + # with uncommited modifications + $result = `cd "$opt_t" && echo "\$(darcs show tags | head -1)-\$((\$(darcs changes --count --from-tag .)-1))"`; + chomp($result); + if(length($result)>1) { + $opt_V = $result; + $foundvcs = 1; + } + # see if working copy has modifications, additions, removals, or missing files + my $hasmod = `darcs whatsnew --repodir="$opt_t" -l`; + if(!$?) { + $opt_V = "$opt_V-dirty"; + } +} if(-d "$opt_t/.hg") { # Mercurial # v1-4-abcdef-dirty # is 4 commits after tag 'v1' with short hash abcdef From 3f462bd032f499d4ff52ecf30380b7a6699e6675 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 27 Aug 2014 17:24:44 -0700 Subject: [PATCH 04/15] check errors --- src/tools/genVersionHeader.pl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index d4f1c52dc..42c0ee531 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -22,44 +22,44 @@ getopts("vt:N:V:") or my ($outfile) = @ARGV; -if(-d "$opt_t/_darcs") { # Darcs +if(!$foundvcs && -d "$opt_t/_darcs") { # Darcs # v1-4-dirty # is tag 'v1' plus 4 patches # with uncommited modifications $result = `cd "$opt_t" && echo "\$(darcs show tags | head -1)-\$((\$(darcs changes --count --from-tag .)-1))"`; chomp($result); - if(length($result)>1) { + if(!$? && length($result)>1) { $opt_V = $result; $foundvcs = 1; - } - # see if working copy has modifications, additions, removals, or missing files - my $hasmod = `darcs whatsnew --repodir="$opt_t" -l`; - if(!$?) { - $opt_V = "$opt_V-dirty"; + # see if working copy has modifications, additions, removals, or missing files + my $hasmod = `darcs whatsnew --repodir="$opt_t" -l`; + if(!$?) { + $opt_V = "$opt_V-dirty"; + } } } -if(-d "$opt_t/.hg") { # Mercurial +if(!$foundvcs && -d "$opt_t/.hg") { # Mercurial # v1-4-abcdef-dirty # is 4 commits after tag 'v1' with short hash abcdef # with uncommited modifications $result = `cd "$opt_t" && hg tip --template '{latesttag}-{latesttagdistance}-{node|short}\n'`; chomp($result); - if(length($result)>1) { + if(!$? && length($result)>1) { $opt_V = $result; $foundvcs = 1; - } - # see if working copy has modifications, additions, removals, or missing files - my $hasmod = `cd "$opt_t" && hg status -m -a -r -d`; - chomp($hasmod); - if(length($hasmod)>0) { - $opt_V = "$opt_V-dirty"; + # see if working copy has modifications, additions, removals, or missing files + my $hasmod = `cd "$opt_t" && hg status -m -a -r -d`; + chomp($hasmod); + if(length($hasmod)>0) { + $opt_V = "$opt_V-dirty"; + } } } if(!$foundvcs && -d "$opt_t/.git") { # same format as Mercurial $result = `git --git-dir="$opt_t/.git" describe --tags --dirty`; chomp($result); - if(length($result)>1) { + if(!$? && length($result)>1) { $opt_V = $result; $foundvcs = 1; } From bc9255ba1c9015270538a8e43b40853d2ba9cf39 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 28 Aug 2014 10:38:24 -0700 Subject: [PATCH 05/15] add version header to example template --- src/template/base/Makefile | 2 + src/template/base/top/exampleApp/Db/Makefile | 1 + .../top/exampleApp/Db/dbVersionExample.db | 5 ++ src/template/base/top/exampleApp/src/Makefile | 12 +++++ .../top/exampleApp/src/_APPNAME_Hello.dbd | 1 + .../base/top/exampleApp/src/devStringIn.c | 52 +++++++++++++++++++ .../base/top/exampleBoot/ioc/st.cmd@Common | 1 + .../base/top/exampleBoot/ioc/st.cmd@RTEMS | 1 + .../base/top/exampleBoot/ioc/st.cmd@vxWorks | 1 + 9 files changed, 76 insertions(+) create mode 100644 src/template/base/top/exampleApp/Db/dbVersionExample.db create mode 100644 src/template/base/top/exampleApp/src/devStringIn.c diff --git a/src/template/base/Makefile b/src/template/base/Makefile index 3cb048b0f..8e3aae45e 100644 --- a/src/template/base/Makefile +++ b/src/template/base/Makefile @@ -28,9 +28,11 @@ TEMPLATES += top/exampleApp/Makefile TEMPLATES += top/exampleApp/Db/Makefile TEMPLATES += top/exampleApp/Db/dbExample1.db TEMPLATES += top/exampleApp/Db/dbExample2.db +TEMPLATES += top/exampleApp/Db/dbVersionExample.db TEMPLATES += top/exampleApp/Db/dbSubExample.db TEMPLATES += top/exampleApp/Db/user.substitutions TEMPLATES += top/exampleApp/src/Makefile +TEMPLATES += top/exampleApp/src/devStringIn.c TEMPLATES += top/exampleApp/src/xxxRecord.dbd TEMPLATES += top/exampleApp/src/xxxRecord.c TEMPLATES += top/exampleApp/src/devXxxSoft.c diff --git a/src/template/base/top/exampleApp/Db/Makefile b/src/template/base/top/exampleApp/Db/Makefile index 3adbf09a5..86bc0d620 100644 --- a/src/template/base/top/exampleApp/Db/Makefile +++ b/src/template/base/top/exampleApp/Db/Makefile @@ -12,6 +12,7 @@ include $(TOP)/configure/CONFIG # databases, templates, substitutions like this DB += dbExample1.db DB += dbExample2.db +DB += dbVersionExample.db DB += dbSubExample.db DB += user.substitutions diff --git a/src/template/base/top/exampleApp/Db/dbVersionExample.db b/src/template/base/top/exampleApp/Db/dbVersionExample.db new file mode 100644 index 000000000..bd1c175df --- /dev/null +++ b/src/template/base/top/exampleApp/Db/dbVersionExample.db @@ -0,0 +1,5 @@ +record(stringin, "$(user):version") { + field(DTYP, "My Version") + field(DESC, "Module version") + field(PINI, "YES") +} diff --git a/src/template/base/top/exampleApp/src/Makefile b/src/template/base/top/exampleApp/src/Makefile index 243cd926f..4d6b21485 100644 --- a/src/template/base/top/exampleApp/src/Makefile +++ b/src/template/base/top/exampleApp/src/Makefile @@ -17,6 +17,7 @@ DBD += xxxSupport.dbd # Compile and add the code to the support library _APPNAME_Support_SRCS += xxxRecord.c _APPNAME_Support_SRCS += devXxxSoft.c +_APPNAME_Support_SRCS += devStringIn.c # Link locally-provided code into the support library, # rather than directly into the IOC application. @@ -26,6 +27,14 @@ _APPNAME_Support_SRCS += initTrace.c _APPNAME_Support_LIBS += $(EPICS_BASE_IOC_LIBS) +# Generate a header which defines a macro with a version string +# from VCS system, or the default +VERHEADER = mymodversion.h +# The macro name to use (default is MODULEVERSION) +MODMACRO = MYMODVERSION +# Default version string if no VCS system in use +MODVERSION = defaultversionstring + #============================= # Build the IOC application @@ -81,3 +90,6 @@ include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE +# Dependency for the generated header +# must be explicit +devStringIn$(DEP): $(VERHEADER) diff --git a/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd b/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd index 64eb0389a..5be6cdc04 100644 --- a/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd +++ b/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd @@ -1 +1,2 @@ registrar(helloRegister) +device(stringin,INST_IO,devSiMyModVersion,"My Version") diff --git a/src/template/base/top/exampleApp/src/devStringIn.c b/src/template/base/top/exampleApp/src/devStringIn.c new file mode 100644 index 000000000..3aa3fc94a --- /dev/null +++ b/src/template/base/top/exampleApp/src/devStringIn.c @@ -0,0 +1,52 @@ +/* devStringIn.c */ +/* Example device support module for stringinRecord */ + +#include +#include +#include +#include + +#include "recGbl.h" +#include "alarm.h" +#include "recSup.h" +#include "devSup.h" +#include "stringinRecord.h" + +#include "mymodversion.h" + + +static long init_record(stringinRecord *prec) +{ + return 0; /* no initialization needed */ +} + +static long read_si(stringinRecord *prec) +{ + size_t N = strlen(MYMODVERSION); + if(Nval, MYMODVERSION); + } else { + /* Not enough space, set an alarm */ + (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + } + return 0; +} + +#include "epicsExport.h" + +static struct { + long number; + DEVSUPFUN report; + DEVSUPFUN init; + DEVSUPFUN init_record; + DEVSUPFUN get_ioint_info; + DEVSUPFUN read_si; +}devSiMyModVersion={ + 5, + NULL, + NULL, + init_record, + NULL, + read_si, +}; +epicsExportAddress(dset,devSiMyModVersion); diff --git a/src/template/base/top/exampleBoot/ioc/st.cmd@Common b/src/template/base/top/exampleBoot/ioc/st.cmd@Common index 76360dd08..c4eb081ba 100644 --- a/src/template/base/top/exampleBoot/ioc/st.cmd@Common +++ b/src/template/base/top/exampleBoot/ioc/st.cmd@Common @@ -13,6 +13,7 @@ _CSAFEAPPNAME__registerRecordDeviceDriver pdbbase ## Load record instances dbLoadTemplate "db/user.substitutions" +dbLoadRecords "db/dbVersionExample.db", "user=_USER_" dbLoadRecords "db/dbSubExample.db", "user=_USER_" ## Set this to see messages from mySub diff --git a/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS b/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS index 4addc5c29..7b6319608 100644 --- a/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS +++ b/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS @@ -11,6 +11,7 @@ _CSAFEAPPNAME__registerRecordDeviceDriver(pdbbase) ## Load record instances dbLoadTemplate("db/user.substitutions") +dbLoadRecords("db/dbVersionExample.db", "user=_USER_") dbLoadRecords("db/dbSubExample.db", "user=_USER_") ## Set this to see messages from mySub diff --git a/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks b/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks index 27ad0572b..d8a2077ce 100644 --- a/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks +++ b/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks @@ -20,6 +20,7 @@ _CSAFEAPPNAME__registerRecordDeviceDriver pdbbase ## Load record instances dbLoadTemplate "db/user.substitutions" +dbLoadRecords "db/dbVersionExample.db", "user=_USER_" dbLoadRecords "db/dbSubExample.db", "user=_USER_" ## Set this to see messages from mySub From e24d4637c9271f8d4c37c927e999658da11f08e7 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Aug 2014 09:56:32 -0700 Subject: [PATCH 06/15] genVersionHeader: use date+time as the default version number --- configure/RULES_BUILD | 4 ++-- src/tools/genVersionHeader.pl | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 0af9b6e55..516c1eaaf 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -364,11 +364,11 @@ tapfiles: $(TESTSCRIPTS) $(TAPFILES) ifneq ($(VERHEADER),) GENVERSIONHEADER ?= $(PERL) $(TOOLS)/genVersionHeader.pl -MODVERSION ?= undefined +#MODVERSION = defaultversionnumber MODMACRO ?= MODULEVERSION $(VERHEADER):: - $(GENVERSIONHEADER) -t $(TOP) -V $(MODVERSION) -N $(MODMACRO) $@ + $(GENVERSIONHEADER) -t "$(TOP)" -V "$(MODVERSION)" -N "$(MODMACRO)" $@ endif diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index 42c0ee531..19c28edd7 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -6,13 +6,13 @@ # use EPICS::Getopts; +use POSIX qw(strftime); use strict; our($opt_v,$opt_t,$opt_N,$opt_V); $opt_N = "MODVERSION"; -$opt_V = "undefined"; $opt_t = "."; my $foundvcs = 0; my $result; @@ -22,6 +22,12 @@ getopts("vt:N:V:") or my ($outfile) = @ARGV; +chomp($opt_V); +if(!$opt_V) { + # RFC 8601 date+time w/ zone (eg "2014-08-29T09:42:47-0700") + $opt_V = strftime "%Y-%m-%dT%H:%M:%S%z", localtime; +} + if(!$foundvcs && -d "$opt_t/_darcs") { # Darcs # v1-4-dirty # is tag 'v1' plus 4 patches From 95d0d97f6af5d347323c59163a90d95c78b9ad51 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Aug 2014 10:58:18 -0700 Subject: [PATCH 07/15] more consistent macro names --- configure/RULES_BUILD | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 516c1eaaf..2b836ce2c 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -362,13 +362,15 @@ tapfiles: $(TESTSCRIPTS) $(TAPFILES) #--------------------------------------------------------------- # Generate header with version number from VCS -ifneq ($(VERHEADER),) -GENVERSIONHEADER ?= $(PERL) $(TOOLS)/genVersionHeader.pl -#MODVERSION = defaultversionnumber -MODMACRO ?= MODULEVERSION +ifneq ($(GENVERSION),) +GENERATEVERSIONHEADERCMD ?= $(PERL) $(TOOLS)/genVersionHeader.pl +# C macro name +GENVERSIONMACRO ?= MODULEVERSION +# C macro default (empty uses date+time) +#GENVERSIONDEFAULT = defaultversionnumber -$(VERHEADER):: - $(GENVERSIONHEADER) -t "$(TOP)" -V "$(MODVERSION)" -N "$(MODMACRO)" $@ +$(GENVERSION):: + $(GENERATEVERSIONHEADERCMD) -t "$(TOP)" -V "$(GENVERSIONDEFAULT)" -N "$(GENVERSIONMACRO)" $@ endif From 75321140ef05d1510b135120df7819cc1ba9fb17 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Aug 2014 10:58:18 -0700 Subject: [PATCH 08/15] update example template --- src/template/base/Makefile | 2 +- src/template/base/top/exampleApp/src/Makefile | 12 ++++-------- ...{devStringIn.c => devStringInGenVersion.c} | 19 +++++++------------ 3 files changed, 12 insertions(+), 21 deletions(-) rename src/template/base/top/exampleApp/src/{devStringIn.c => devStringInGenVersion.c} (72%) diff --git a/src/template/base/Makefile b/src/template/base/Makefile index 8e3aae45e..f2292c4e5 100644 --- a/src/template/base/Makefile +++ b/src/template/base/Makefile @@ -32,7 +32,7 @@ TEMPLATES += top/exampleApp/Db/dbVersionExample.db TEMPLATES += top/exampleApp/Db/dbSubExample.db TEMPLATES += top/exampleApp/Db/user.substitutions TEMPLATES += top/exampleApp/src/Makefile -TEMPLATES += top/exampleApp/src/devStringIn.c +TEMPLATES += top/exampleApp/src/devStringInGenVersion.c TEMPLATES += top/exampleApp/src/xxxRecord.dbd TEMPLATES += top/exampleApp/src/xxxRecord.c TEMPLATES += top/exampleApp/src/devXxxSoft.c diff --git a/src/template/base/top/exampleApp/src/Makefile b/src/template/base/top/exampleApp/src/Makefile index 4d6b21485..a419167b8 100644 --- a/src/template/base/top/exampleApp/src/Makefile +++ b/src/template/base/top/exampleApp/src/Makefile @@ -17,7 +17,7 @@ DBD += xxxSupport.dbd # Compile and add the code to the support library _APPNAME_Support_SRCS += xxxRecord.c _APPNAME_Support_SRCS += devXxxSoft.c -_APPNAME_Support_SRCS += devStringIn.c +_APPNAME_Support_SRCS += devStringInGenVersion.c # Link locally-provided code into the support library, # rather than directly into the IOC application. @@ -28,12 +28,8 @@ _APPNAME_Support_SRCS += initTrace.c _APPNAME_Support_LIBS += $(EPICS_BASE_IOC_LIBS) # Generate a header which defines a macro with a version string -# from VCS system, or the default -VERHEADER = mymodversion.h -# The macro name to use (default is MODULEVERSION) -MODMACRO = MYMODVERSION -# Default version string if no VCS system in use -MODVERSION = defaultversionstring +# with the date and time, or a revision id from VCS system if available +GENVERSION = mymodversion.h #============================= # Build the IOC application @@ -92,4 +88,4 @@ include $(TOP)/configure/RULES # Dependency for the generated header # must be explicit -devStringIn$(DEP): $(VERHEADER) +devStringInGenVersion$(DEP): $(GENVERSION) diff --git a/src/template/base/top/exampleApp/src/devStringIn.c b/src/template/base/top/exampleApp/src/devStringInGenVersion.c similarity index 72% rename from src/template/base/top/exampleApp/src/devStringIn.c rename to src/template/base/top/exampleApp/src/devStringInGenVersion.c index 3aa3fc94a..21fd09bfc 100644 --- a/src/template/base/top/exampleApp/src/devStringIn.c +++ b/src/template/base/top/exampleApp/src/devStringInGenVersion.c @@ -14,26 +14,21 @@ #include "mymodversion.h" - -static long init_record(stringinRecord *prec) -{ - return 0; /* no initialization needed */ -} +/* must be last include */ +#include "epicsExport.h" static long read_si(stringinRecord *prec) { - size_t N = strlen(MYMODVERSION); - if(Nval, MYMODVERSION); + size_t N = strlen(MODULEVERSION); + if(Nval)) { + strcpy(prec->val, MODULEVERSION); } else { - /* Not enough space, set an alarm */ + /* Not enough space, so signal an alarm */ (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); } return 0; } -#include "epicsExport.h" - static struct { long number; DEVSUPFUN report; @@ -45,7 +40,7 @@ static struct { 5, NULL, NULL, - init_record, + NULL, NULL, read_si, }; From 79497c359c133c6ce48e6637a3145e8e5fdf8e7e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 29 Aug 2014 11:05:56 -0700 Subject: [PATCH 09/15] add release note --- documentation/RELEASE_NOTES.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 3db8233c0..99a32458e 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -15,6 +15,16 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.

Changes between 3.15.0.1 and 3.15.0.2

+

Generate Version Header

+ +

A Perl script and Makefile rules are added to allow modules +to generate a C header file with a macro defined with an automatically updated identifier. +This is a VCS revision ID (Darcs, Git, and Mercurial supported) or +the time of the build if not VCS system is in use.

+ +

The example template is updated with a demonstration which makes this +identifier visible with a stringin record.

+

Implement EPICS_CAS_INTF_ADDR_LIST in rsrv

The IOC server can now bind to a single IP address (and optional port number) From 1240f097973ac5cfa6b83a92c7e2e9240bccc832 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 1 Jun 2015 19:19:24 -0400 Subject: [PATCH 10/15] genVersionHeader: update HG, add SVN and BZR Update the HG case to use --cwd to avoid dependence on shell syntax. --- src/tools/genVersionHeader.pl | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index 19c28edd7..28ae666e6 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -48,13 +48,13 @@ if(!$foundvcs && -d "$opt_t/.hg") { # Mercurial # v1-4-abcdef-dirty # is 4 commits after tag 'v1' with short hash abcdef # with uncommited modifications - $result = `cd "$opt_t" && hg tip --template '{latesttag}-{latesttagdistance}-{node|short}\n'`; + $result = `hg --cwd "$opt_t" tip --template '{latesttag}-{latesttagdistance}-{node|short}\n'`; chomp($result); if(!$? && length($result)>1) { $opt_V = $result; $foundvcs = 1; # see if working copy has modifications, additions, removals, or missing files - my $hasmod = `cd "$opt_t" && hg status -m -a -r -d`; + my $hasmod = `hg --cwd "$opt_t" status -m -a -r -d`; chomp($hasmod); if(length($hasmod)>0) { $opt_V = "$opt_V-dirty"; @@ -70,6 +70,38 @@ if(!$foundvcs && -d "$opt_t/.git") { $foundvcs = 1; } } +if(!$foundvcs && -d "$opt_t/.svn") { + # 12345 + $result = `cd "$opt_t" && svn info --non-interactive`; + chomp($result); + if(!$? && $result =~ /^Revision:\s*(\d+)/m) { + $opt_V = $1; + $foundvcs = 1; + # see if working copy has modifications, additions, removals, or missing files + my $hasmod = `cd "$opt_t" && svn status -q --non-interactive`; + chomp($hasmod); + if(length($hasmod)>0) { + $opt_V = "$opt_V-dirty"; + } + } +} +if(!$foundvcs && -d "$opt_t/.bzr") { + # 12444-anj@aps.anl.gov-20131003210403-icfd8mc37g8vctpf + $result = `cd "$opt_t" && bzr version-info -q --custom --template="{revno}-{revision_id}"`; + chomp($result); + print "BZR $result"; + if(!$? && length($result)>1) { + $opt_V = $result; + $foundvcs = 1; + # see if working copy has modifications, additions, removals, or missing files + # unfortunately "bzr version-info --check-clean ..." doesn't seem to work as documented + my $hasmod = `cd "$opt_t" && bzr status -SV`; + chomp($hasmod); + if(length($hasmod)>0) { + $opt_V = "$opt_V-dirty"; + } + } +} my $output = "#ifndef $opt_N\n# define $opt_N \"$opt_V\"\n#endif\n"; print "== would\n$output" if $opt_v; @@ -80,12 +112,12 @@ if(open($DST, '+<', $outfile)) { print "== have\n$actual" if $opt_v; if($actual eq $output) { - print "Keeping existing VCS version header $outfile\n"; + print "Keeping existing VCS version header $outfile with \"$opt_V\"\n"; exit(0) } - print "Updating VCS version header $outfile\n"; + print "Updating VCS version header $outfile with \"$opt_V\"\n"; } else { - print "Creating VCS version header $outfile\n"; + print "Creating VCS version header $outfile with \"$opt_V\"\n"; open($DST, '>', $outfile) or die "Unable to open or create VCS version header $outfile"; } From 7fd4ac5a67becdb386144e27c4439d99345a80fb Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 1 Jun 2015 19:19:24 -0400 Subject: [PATCH 11/15] update template use waveform as long string use app. name in header and macro name --- src/template/base/Makefile | 2 +- .../top/exampleApp/Db/dbVersionExample.db | 6 +- src/template/base/top/exampleApp/src/Makefile | 8 ++- .../top/exampleApp/src/_APPNAME_Hello.dbd | 2 +- .../base/top/exampleApp/src/devGenVersion.c | 56 +++++++++++++++++++ .../exampleApp/src/devStringInGenVersion.c | 47 ---------------- 6 files changed, 67 insertions(+), 54 deletions(-) create mode 100644 src/template/base/top/exampleApp/src/devGenVersion.c delete mode 100644 src/template/base/top/exampleApp/src/devStringInGenVersion.c diff --git a/src/template/base/Makefile b/src/template/base/Makefile index f2292c4e5..4e7de23d3 100644 --- a/src/template/base/Makefile +++ b/src/template/base/Makefile @@ -32,7 +32,7 @@ TEMPLATES += top/exampleApp/Db/dbVersionExample.db TEMPLATES += top/exampleApp/Db/dbSubExample.db TEMPLATES += top/exampleApp/Db/user.substitutions TEMPLATES += top/exampleApp/src/Makefile -TEMPLATES += top/exampleApp/src/devStringInGenVersion.c +TEMPLATES += top/exampleApp/src/devGenVersion.c TEMPLATES += top/exampleApp/src/xxxRecord.dbd TEMPLATES += top/exampleApp/src/xxxRecord.c TEMPLATES += top/exampleApp/src/devXxxSoft.c diff --git a/src/template/base/top/exampleApp/Db/dbVersionExample.db b/src/template/base/top/exampleApp/Db/dbVersionExample.db index bd1c175df..e86b75dc4 100644 --- a/src/template/base/top/exampleApp/Db/dbVersionExample.db +++ b/src/template/base/top/exampleApp/Db/dbVersionExample.db @@ -1,5 +1,7 @@ -record(stringin, "$(user):version") { - field(DTYP, "My Version") +record(waveform, "$(user):version") { + field(DTYP, "Module Version") field(DESC, "Module version") + field(FTVL, "CHAR") + field(NELM, "$(NELM=200)") field(PINI, "YES") } diff --git a/src/template/base/top/exampleApp/src/Makefile b/src/template/base/top/exampleApp/src/Makefile index a419167b8..0c127999b 100644 --- a/src/template/base/top/exampleApp/src/Makefile +++ b/src/template/base/top/exampleApp/src/Makefile @@ -17,7 +17,7 @@ DBD += xxxSupport.dbd # Compile and add the code to the support library _APPNAME_Support_SRCS += xxxRecord.c _APPNAME_Support_SRCS += devXxxSoft.c -_APPNAME_Support_SRCS += devStringInGenVersion.c +_APPNAME_Support_SRCS += devGenVersion.c # Link locally-provided code into the support library, # rather than directly into the IOC application. @@ -29,7 +29,9 @@ _APPNAME_Support_LIBS += $(EPICS_BASE_IOC_LIBS) # Generate a header which defines a macro with a version string # with the date and time, or a revision id from VCS system if available -GENVERSION = mymodversion.h +GENVERSION = _APPNAME_Version.h +# Macro name +GENVERSIONMACRO = _APPNAME_VERSION #============================= # Build the IOC application @@ -88,4 +90,4 @@ include $(TOP)/configure/RULES # Dependency for the generated header # must be explicit -devStringInGenVersion$(DEP): $(GENVERSION) +devGenVersion$(DEP): $(GENVERSION) diff --git a/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd b/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd index 5be6cdc04..47f187050 100644 --- a/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd +++ b/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd @@ -1,2 +1,2 @@ registrar(helloRegister) -device(stringin,INST_IO,devSiMyModVersion,"My Version") +device(waveform,INST_IO,devWfMyModVersion,"Module Version") diff --git a/src/template/base/top/exampleApp/src/devGenVersion.c b/src/template/base/top/exampleApp/src/devGenVersion.c new file mode 100644 index 000000000..297b69138 --- /dev/null +++ b/src/template/base/top/exampleApp/src/devGenVersion.c @@ -0,0 +1,56 @@ +/* devGenVersion.c */ +/* Example device support providing the module version string as a charactor array (long string) */ + +#include +#include +#include +#include + +#include "recGbl.h" +#include "alarm.h" +#include "recSup.h" +#include "devSup.h" +#include "menuFtype.h" +#include "waveformRecord.h" + +#include "_APPNAME_Version.h" + +/* must be last include */ +#include "epicsExport.h" + +static long read_wf(waveformRecord *prec) +{ + size_t N = strlen(_APPNAME_VERSION)+1; + char *buf = prec->bptr; + + if(prec->ftvl!=menuFtypeCHAR) { + (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); + return 0; + } + + if(N>=prec->nelm) + N = prec->nelm; + prec->nord = N; + + memcpy(buf, _APPNAME_VERSION, N); + buf[prec->nelm-1] = '\0'; + + return 0; +} + +static struct { + long number; + DEVSUPFUN report; + DEVSUPFUN init; + DEVSUPFUN init_record; + DEVSUPFUN get_ioint_info; + DEVSUPFUN read_si; +}devWfMyModVersion={ + 5, + NULL, + NULL, + NULL, + NULL, + read_wf, +}; +epicsExportAddress(dset,devWfMyModVersion); diff --git a/src/template/base/top/exampleApp/src/devStringInGenVersion.c b/src/template/base/top/exampleApp/src/devStringInGenVersion.c deleted file mode 100644 index 21fd09bfc..000000000 --- a/src/template/base/top/exampleApp/src/devStringInGenVersion.c +++ /dev/null @@ -1,47 +0,0 @@ -/* devStringIn.c */ -/* Example device support module for stringinRecord */ - -#include -#include -#include -#include - -#include "recGbl.h" -#include "alarm.h" -#include "recSup.h" -#include "devSup.h" -#include "stringinRecord.h" - -#include "mymodversion.h" - -/* must be last include */ -#include "epicsExport.h" - -static long read_si(stringinRecord *prec) -{ - size_t N = strlen(MODULEVERSION); - if(Nval)) { - strcpy(prec->val, MODULEVERSION); - } else { - /* Not enough space, so signal an alarm */ - (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); - } - return 0; -} - -static struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_si; -}devSiMyModVersion={ - 5, - NULL, - NULL, - NULL, - NULL, - read_si, -}; -epicsExportAddress(dset,devSiMyModVersion); From 60823bd2fb2915301354ed3bec193095b260c9df Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 8 Jul 2015 16:46:34 -0500 Subject: [PATCH 12/15] Some edits to the Perl script --- src/tools/genVersionHeader.pl | 121 ++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 51 deletions(-) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index 28ae666e6..43bec8d80 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -1,128 +1,147 @@ #!/usr/bin/env perl +#************************************************************************* +# Copyright (c) 2014 Brookhaven National Laboratory. +# EPICS BASE is distributed subject to a Software License Agreement found +# in file LICENSE that is included with this distribution. +#************************************************************************* # # Generate a C header file which # defines a macro with a string # describing the VCS revision # +use FindBin qw($Bin); +use lib "$Bin/../../lib/perl"; + use EPICS::Getopts; use POSIX qw(strftime); use strict; -our($opt_v,$opt_t,$opt_N,$opt_V); +# RFC 8601 date+time w/ zone (eg "2014-08-29T09:42:47-0700") +my $tfmt = '%Y-%m-%dT%H:%M:%S'; +$tfmt .= '%z' unless $^O eq 'MSWin32'; # %z returns zone name on Windows + +our ($opt_h, $opt_v); +our $opt_t = '.'; +our $opt_N = 'VCSVERSION'; +our $opt_V = strftime($tfmt, localtime); -$opt_N = "MODVERSION"; -$opt_t = "."; my $foundvcs = 0; my $result; -getopts("vt:N:V:") or - die "Usage: genVersionHeader.pl [-t top] [-N NAME] [-V VERSION] output.h"; +getopts('hvt:N:V:') && @ARGV == 1 + or HELP_MESSAGE(); my ($outfile) = @ARGV; -chomp($opt_V); -if(!$opt_V) { - # RFC 8601 date+time w/ zone (eg "2014-08-29T09:42:47-0700") - $opt_V = strftime "%Y-%m-%dT%H:%M:%S%z", localtime; -} - -if(!$foundvcs && -d "$opt_t/_darcs") { # Darcs +if (!$foundvcs && -d "$opt_t/_darcs") { # Darcs # v1-4-dirty # is tag 'v1' plus 4 patches # with uncommited modifications $result = `cd "$opt_t" && echo "\$(darcs show tags | head -1)-\$((\$(darcs changes --count --from-tag .)-1))"`; - chomp($result); - if(!$? && length($result)>1) { + chomp $result; + if (!$? && length($result) > 1) { $opt_V = $result; $foundvcs = 1; # see if working copy has modifications, additions, removals, or missing files my $hasmod = `darcs whatsnew --repodir="$opt_t" -l`; - if(!$?) { - $opt_V = "$opt_V-dirty"; - } + $opt_V .= '-dirty' unless $?; } } -if(!$foundvcs && -d "$opt_t/.hg") { # Mercurial +if (!$foundvcs && -d "$opt_t/.hg") { # Mercurial # v1-4-abcdef-dirty # is 4 commits after tag 'v1' with short hash abcdef # with uncommited modifications $result = `hg --cwd "$opt_t" tip --template '{latesttag}-{latesttagdistance}-{node|short}\n'`; - chomp($result); - if(!$? && length($result)>1) { + chomp $result; + if (!$? && length($result)>1) { $opt_V = $result; $foundvcs = 1; # see if working copy has modifications, additions, removals, or missing files my $hasmod = `hg --cwd "$opt_t" status -m -a -r -d`; - chomp($hasmod); - if(length($hasmod)>0) { - $opt_V = "$opt_V-dirty"; - } + chomp $hasmod; + $opt_V .= '-dirty' if length($hasmod) > 0; } } -if(!$foundvcs && -d "$opt_t/.git") { +if (!$foundvcs && -d "$opt_t/.git") { # same format as Mercurial $result = `git --git-dir="$opt_t/.git" describe --tags --dirty`; - chomp($result); - if(!$? && length($result)>1) { + chomp $result; + if (!$? && length($result) > 1) { $opt_V = $result; $foundvcs = 1; } } -if(!$foundvcs && -d "$opt_t/.svn") { +if (!$foundvcs && -d "$opt_t/.svn") { # 12345 $result = `cd "$opt_t" && svn info --non-interactive`; - chomp($result); - if(!$? && $result =~ /^Revision:\s*(\d+)/m) { + chomp $result; + if (!$? && $result =~ /^Revision:\s*(\d+)/m) { $opt_V = $1; $foundvcs = 1; # see if working copy has modifications, additions, removals, or missing files my $hasmod = `cd "$opt_t" && svn status -q --non-interactive`; - chomp($hasmod); - if(length($hasmod)>0) { - $opt_V = "$opt_V-dirty"; - } + chomp $hasmod; + $opt_V .= '-dirty' if length($hasmod) > 0; } } -if(!$foundvcs && -d "$opt_t/.bzr") { +if (!$foundvcs && -d "$opt_t/.bzr") { # 12444-anj@aps.anl.gov-20131003210403-icfd8mc37g8vctpf $result = `cd "$opt_t" && bzr version-info -q --custom --template="{revno}-{revision_id}"`; - chomp($result); - print "BZR $result"; - if(!$? && length($result)>1) { + chomp $result; + if (!$? && length($result)>1) { $opt_V = $result; $foundvcs = 1; # see if working copy has modifications, additions, removals, or missing files # unfortunately "bzr version-info --check-clean ..." doesn't seem to work as documented my $hasmod = `cd "$opt_t" && bzr status -SV`; - chomp($hasmod); - if(length($hasmod)>0) { - $opt_V = "$opt_V-dirty"; - } + chomp $hasmod; + $opt_V .= '-dirty' if length($hasmod) > 0; } } -my $output = "#ifndef $opt_N\n# define $opt_N \"$opt_V\"\n#endif\n"; +my $output = << "__END"; +/* Generated file, do not edit! */ + +#ifndef $opt_N +# define $opt_N \"$opt_V\" +#endif +__END print "== would\n$output" if $opt_v; my $DST; -if(open($DST, '+<', $outfile)) { - my $actual = join("", <$DST>); +if (open($DST, '+<', $outfile)) { + my $actual = join('', <$DST>); print "== have\n$actual" if $opt_v; - if($actual eq $output) { + if ($actual eq $output) { print "Keeping existing VCS version header $outfile with \"$opt_V\"\n"; - exit(0) + exit 0; } print "Updating VCS version header $outfile with \"$opt_V\"\n"; } else { print "Creating VCS version header $outfile with \"$opt_V\"\n"; - open($DST, '>', $outfile) or die "Unable to open or create VCS version header $outfile"; + open($DST, '>', $outfile) + or die "Unable to open or create VCS version header $outfile"; } -seek($DST,0,0); -truncate($DST,0); +seek $DST, 0, 0; +truncate $DST, 0; print $DST $output; +close $DST; + +sub HELP_MESSAGE { + print STDERR < Date: Fri, 10 Jul 2015 12:09:37 -0500 Subject: [PATCH 13/15] Updates to build rules and genVersionHeader.pl script Added -q (quiet) flag, renamed INSTALL_QUIETLY build variable. Moved GENVERSION variables into normal locations. Changed from :: rule to : rule with FORCE dependency. Removed use of --git-dir, only works when CWD is TOP. Simplified some parts, more perlish. Added VCS used to generated output file. Expanded on the -v (verbose) output. --- configure/CONFIG_BASE | 4 +- configure/CONFIG_COMMON | 9 ++ configure/RULES_BUILD | 13 +- src/template/base/top/exampleApp/src/Makefile | 5 +- src/tools/genVersionHeader.pl | 118 +++++++++++------- 5 files changed, 87 insertions(+), 62 deletions(-) diff --git a/configure/CONFIG_BASE b/configure/CONFIG_BASE index e416f99db..6eac3b2e0 100644 --- a/configure/CONFIG_BASE +++ b/configure/CONFIG_BASE @@ -63,11 +63,11 @@ DBTOMENUH = $(PERL) $(TOOLS)/dbdToMenuH.pl REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl CONVERTRELEASE = $(PERL) $(TOOLS)/convertRelease.pl FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl +GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG) #------------------------------------------------------- # tools for installing libraries and products -INSTALL_QUIETLY := $(if $(findstring s,$(MAKEFLAGS)),-q,) -INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(INSTALL_QUIETLY) +INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(QUIET_FLAG) INSTALL_PRODUCT = $(INSTALL) INSTALL_LIBRARY = $(INSTALL) diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index 584175784..9e82b13b0 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -85,6 +85,7 @@ IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION)) # Make echo output - suppress echoing if make's '-s' flag is set NOP = : ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo) +QUIET_FLAG := $(if $(findstring s,$(MAKEFLAGS)),-q,) #------------------------------------------------------- ifdef T_A @@ -327,6 +328,14 @@ COMPILE.cpp = $(CCC) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) # C preprocessor command PREPROCESS.cpp = $(CPP) $(CPPFLAGS) $(INCLUDES) $< > $@ +#-------------------------------------------------- +# genVersion header defaults + +# C macro name +GENVERSIONMACRO = VCSVERSION +# C macro default value (empty to use date+time) +GENVERSIONDEFAULT = + #-------------------------------------------------- # Header dependency file generation diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index 2b836ce2c..7ec79d569 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -363,15 +363,8 @@ tapfiles: $(TESTSCRIPTS) $(TAPFILES) # Generate header with version number from VCS ifneq ($(GENVERSION),) -GENERATEVERSIONHEADERCMD ?= $(PERL) $(TOOLS)/genVersionHeader.pl -# C macro name -GENVERSIONMACRO ?= MODULEVERSION -# C macro default (empty uses date+time) -#GENVERSIONDEFAULT = defaultversionnumber - -$(GENVERSION):: - $(GENERATEVERSIONHEADERCMD) -t "$(TOP)" -V "$(GENVERSIONDEFAULT)" -N "$(GENVERSIONMACRO)" $@ - +$(COMMON_DIR)/$(GENVERSION): FORCE + $(GENVERSIONHEADER) -t $(TOP) -N $(GENVERSIONMACRO) -V "$(GENVERSIONDEFAULT)" $@ endif #--------------------------------------------------------------- @@ -503,7 +496,7 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: % .PRECIOUS: $(COMMON_INC) .PHONY: all host inc build install clean rebuild buildInstall build_clean -.PHONY: runtests tapfiles checkRelease warnRelease noCheckRelease +.PHONY: runtests tapfiles checkRelease warnRelease noCheckRelease FORCE endif # BASE_RULES_BUILD # EOF RULES_BUILD diff --git a/src/template/base/top/exampleApp/src/Makefile b/src/template/base/top/exampleApp/src/Makefile index 0c127999b..2a301d872 100644 --- a/src/template/base/top/exampleApp/src/Makefile +++ b/src/template/base/top/exampleApp/src/Makefile @@ -88,6 +88,5 @@ include $(TOP)/configure/RULES #---------------------------------------- # ADD RULES AFTER THIS LINE -# Dependency for the generated header -# must be explicit -devGenVersion$(DEP): $(GENVERSION) +# Explicit dependency needed for generated header file +dev_APPNAME_Version$(DEP): $(COMMON_DIR)/$(GENVERSION) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index 43bec8d80..f078ad4f6 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -21,109 +21,131 @@ use strict; # RFC 8601 date+time w/ zone (eg "2014-08-29T09:42:47-0700") my $tfmt = '%Y-%m-%dT%H:%M:%S'; $tfmt .= '%z' unless $^O eq 'MSWin32'; # %z returns zone name on Windows +my $now = strftime($tfmt, localtime); -our ($opt_h, $opt_v); +our ($opt_h, $opt_v, $opt_q); our $opt_t = '.'; our $opt_N = 'VCSVERSION'; -our $opt_V = strftime($tfmt, localtime); +our $opt_V = $now; -my $foundvcs = 0; -my $result; +my $vcs; -getopts('hvt:N:V:') && @ARGV == 1 +getopts('hvqt:N:V:') && @ARGV == 1 or HELP_MESSAGE(); my ($outfile) = @ARGV; -if (!$foundvcs && -d "$opt_t/_darcs") { # Darcs +if (!$vcs && -d "$opt_t/_darcs") { # Darcs + print "== Found /_darcs directory\n" if $opt_v; # v1-4-dirty # is tag 'v1' plus 4 patches # with uncommited modifications - $result = `cd "$opt_t" && echo "\$(darcs show tags | head -1)-\$((\$(darcs changes --count --from-tag .)-1))"`; + my $result = `cd "$opt_t" && echo "\$(darcs show tags | head -1)-\$((\$(darcs changes --count --from-tag .)-1))"`; chomp $result; - if (!$? && length($result) > 1) { + print "== darcs show tags, changes:\n$result\n==\n" if $opt_v; + if (!$? && $result ne '') { $opt_V = $result; - $foundvcs = 1; + $vcs = 'Darcs'; # see if working copy has modifications, additions, removals, or missing files my $hasmod = `darcs whatsnew --repodir="$opt_t" -l`; $opt_V .= '-dirty' unless $?; } } -if (!$foundvcs && -d "$opt_t/.hg") { # Mercurial +if (!$vcs && -d "$opt_t/.hg") { # Mercurial + print "== Found /.hg directory\n" if $opt_v; # v1-4-abcdef-dirty # is 4 commits after tag 'v1' with short hash abcdef # with uncommited modifications - $result = `hg --cwd "$opt_t" tip --template '{latesttag}-{latesttagdistance}-{node|short}\n'`; - chomp $result; - if (!$? && length($result)>1) { + my $result = `hg tip --template '{latesttag}-{latesttagdistance}-{node|short}'`; + print "== hg tip:\n$result\n==\n" if $opt_v; + if (!$? && $result ne '') { $opt_V = $result; - $foundvcs = 1; + $vcs = 'Mercurial'; # see if working copy has modifications, additions, removals, or missing files - my $hasmod = `hg --cwd "$opt_t" status -m -a -r -d`; + my $hasmod = `hg status -m -a -r -d`; chomp $hasmod; - $opt_V .= '-dirty' if length($hasmod) > 0; + $opt_V .= '-dirty' if $hasmod ne ''; } } -if (!$foundvcs && -d "$opt_t/.git") { - # same format as Mercurial - $result = `git --git-dir="$opt_t/.git" describe --tags --dirty`; +if (!$vcs && -d "$opt_t/.git") { # Git + print "== Found /.git directory\n" if $opt_v; + # v1-4-abcdef-dirty + # is 4 commits after tag 'v1' with short hash abcdef + # with uncommited modifications + my $result = `git describe --tags --dirty`; chomp $result; - if (!$? && length($result) > 1) { + print "== git describe:\n$result\n==\n" if $opt_v; + if (!$? && $result ne '') { $opt_V = $result; - $foundvcs = 1; + $vcs = 'Git'; } } -if (!$foundvcs && -d "$opt_t/.svn") { - # 12345 - $result = `cd "$opt_t" && svn info --non-interactive`; +if (!$vcs && -d "$opt_t/.svn") { # Subversion + print "== Found /.svn directory\n" if $opt_v; + # 12345-dirty + my $result = `cd "$opt_t" && svn info --non-interactive`; chomp $result; + print "== svn info:\n$result\n==\n" if $opt_v; if (!$? && $result =~ /^Revision:\s*(\d+)/m) { $opt_V = $1; - $foundvcs = 1; + $vcs = 'Subversion'; # see if working copy has modifications, additions, removals, or missing files - my $hasmod = `cd "$opt_t" && svn status -q --non-interactive`; + my $hasmod = `cd "$opt_t" && svn status --non-interactive`; chomp $hasmod; - $opt_V .= '-dirty' if length($hasmod) > 0; + $opt_V .= '-dirty' if $hasmod ne ''; } } -if (!$foundvcs && -d "$opt_t/.bzr") { - # 12444-anj@aps.anl.gov-20131003210403-icfd8mc37g8vctpf - $result = `cd "$opt_t" && bzr version-info -q --custom --template="{revno}-{revision_id}"`; - chomp $result; - if (!$? && length($result)>1) { +if (!$vcs && -d "$opt_t/.bzr") { # Bazaar + print "== Found /.bzr directory\n" if $opt_v; + # 12444-anj@aps.anl.gov-20131003210403-icfd8mc37g8vctpf-dirty + my $result = `bzr version-info -q --custom --template="{revno}-{revision_id}-{clean}"`; + print "== bzr version-info:\n$result\n==\n" if $opt_v; + if (!$? && $result ne '') { + $result =~ s/-([01])$/$1 ? '' : '-dirty'/e; $opt_V = $result; - $foundvcs = 1; - # see if working copy has modifications, additions, removals, or missing files - # unfortunately "bzr version-info --check-clean ..." doesn't seem to work as documented - my $hasmod = `cd "$opt_t" && bzr status -SV`; - chomp $hasmod; - $opt_V .= '-dirty' if length($hasmod) > 0; + $vcs = 'Bazaar'; + } +} +if (!$vcs) { + print "== No VCS directories\n" if $opt_v; + if ($opt_V eq '') { + $vcs = 'build date/time'; + $opt_V = $now; + } + else { + $vcs = 'Makefile'; } } my $output = << "__END"; /* Generated file, do not edit! */ +/* Version determined from $vcs */ + #ifndef $opt_N -# define $opt_N \"$opt_V\" + #define $opt_N \"$opt_V\" #endif __END -print "== would\n$output" if $opt_v; + +print "== Want:\n$output==\n" if $opt_v; my $DST; if (open($DST, '+<', $outfile)) { my $actual = join('', <$DST>); - print "== have\n$actual" if $opt_v; + print "== Current:\n$actual==\n" if $opt_v; if ($actual eq $output) { - print "Keeping existing VCS version header $outfile with \"$opt_V\"\n"; + print "Keeping VCS header $outfile\n $opt_N = \"$opt_V\"\n" + unless $opt_q; exit 0; } - print "Updating VCS version header $outfile with \"$opt_V\"\n"; + print "Updating VCS header $outfile\n $opt_N = \"$opt_V\"\n" + unless $opt_q; } else { - print "Creating VCS version header $outfile with \"$opt_V\"\n"; + print "Creating VCS header $outfile\n $opt_N = \"$opt_V\"\n" + unless $opt_q; open($DST, '>', $outfile) - or die "Unable to open or create VCS version header $outfile"; + or die "Can't create $outfile: $!\n"; } seek $DST, 0, 0; @@ -136,11 +158,13 @@ sub HELP_MESSAGE { Usage: genVersionHeader.pl -h Display this Usage message - genVersionHeader.pl [-v] [-t top] [-N NAME] [-V version] output.h"; + genVersionHeader.pl [-v] [-q] [-t top] [-N NAME] [-V version] output.h"; Generate or update the header file output.h + -v - Verbose (debugging messages) + -q - Quiet -t top - Path to the module's top (default '$opt_t') -N NAME - Macro name to be defined (default '$opt_N') - -v version - Version number if no VCS (default '$opt_V') + -V version - Version if no VCS (e.g. '$opt_V') EOF exit $opt_h ? 0 : 1; } From ed4bcd831f378a6c4f868c99ce3e4d14b0d80c5e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 10 Jul 2015 12:28:49 -0500 Subject: [PATCH 14/15] Update example template, release notes Changed device support to use the long string input rectype. Moved the device registration into its own file. Used _APPNAME_ more, trying to prevent future name clashes. --- documentation/RELEASE_NOTES.html | 12 ++-- src/template/base/Makefile | 5 +- src/template/base/top/exampleApp/Db/Makefile | 2 +- .../top/exampleApp/Db/_APPNAME_Version.db | 6 ++ .../top/exampleApp/Db/dbVersionExample.db | 7 --- src/template/base/top/exampleApp/src/Makefile | 12 ++-- .../top/exampleApp/src/_APPNAME_Hello.dbd | 1 - .../base/top/exampleApp/src/devGenVersion.c | 56 ------------------- .../top/exampleApp/src/dev_APPNAME_Version.c | 38 +++++++++++++ .../exampleApp/src/dev_APPNAME_Version.dbd | 1 + .../base/top/exampleBoot/ioc/st.cmd@Common | 2 +- .../base/top/exampleBoot/ioc/st.cmd@RTEMS | 2 +- .../base/top/exampleBoot/ioc/st.cmd@vxWorks | 2 +- 13 files changed, 65 insertions(+), 81 deletions(-) create mode 100644 src/template/base/top/exampleApp/Db/_APPNAME_Version.db delete mode 100644 src/template/base/top/exampleApp/Db/dbVersionExample.db delete mode 100644 src/template/base/top/exampleApp/src/devGenVersion.c create mode 100644 src/template/base/top/exampleApp/src/dev_APPNAME_Version.c create mode 100644 src/template/base/top/exampleApp/src/dev_APPNAME_Version.dbd diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 99a32458e..88becb3cc 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -17,13 +17,13 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.

Generate Version Header

-

A Perl script and Makefile rules are added to allow modules -to generate a C header file with a macro defined with an automatically updated identifier. -This is a VCS revision ID (Darcs, Git, and Mercurial supported) or -the time of the build if not VCS system is in use.

+

A Perl script and Makefile rules have been added to allow modules to generate +a C header file with a macro defined with an automatically updated identifier. +This is a VCS revision ID (Darcs, Git, Mercurial Subversion and Bazaar are all +supported) or the date/time of the build if no VCS system is in use.

-

The example template is updated with a demonstration which makes this -identifier visible with a stringin record.

+

The makeBaseApp example template has been updated with a new device support +which makes this identifier visible via a lsi (long string input) record.

Implement EPICS_CAS_INTF_ADDR_LIST in rsrv

diff --git a/src/template/base/Makefile b/src/template/base/Makefile index 4e7de23d3..c8c1eed8b 100644 --- a/src/template/base/Makefile +++ b/src/template/base/Makefile @@ -28,11 +28,12 @@ TEMPLATES += top/exampleApp/Makefile TEMPLATES += top/exampleApp/Db/Makefile TEMPLATES += top/exampleApp/Db/dbExample1.db TEMPLATES += top/exampleApp/Db/dbExample2.db -TEMPLATES += top/exampleApp/Db/dbVersionExample.db +TEMPLATES += top/exampleApp/Db/_APPNAME_Version.db TEMPLATES += top/exampleApp/Db/dbSubExample.db TEMPLATES += top/exampleApp/Db/user.substitutions TEMPLATES += top/exampleApp/src/Makefile -TEMPLATES += top/exampleApp/src/devGenVersion.c +TEMPLATES += top/exampleApp/src/dev_APPNAME_Version.c +TEMPLATES += top/exampleApp/src/dev_APPNAME_Version.dbd TEMPLATES += top/exampleApp/src/xxxRecord.dbd TEMPLATES += top/exampleApp/src/xxxRecord.c TEMPLATES += top/exampleApp/src/devXxxSoft.c diff --git a/src/template/base/top/exampleApp/Db/Makefile b/src/template/base/top/exampleApp/Db/Makefile index 86bc0d620..89b452264 100644 --- a/src/template/base/top/exampleApp/Db/Makefile +++ b/src/template/base/top/exampleApp/Db/Makefile @@ -12,7 +12,7 @@ include $(TOP)/configure/CONFIG # databases, templates, substitutions like this DB += dbExample1.db DB += dbExample2.db -DB += dbVersionExample.db +DB += _APPNAME_Version.db DB += dbSubExample.db DB += user.substitutions diff --git a/src/template/base/top/exampleApp/Db/_APPNAME_Version.db b/src/template/base/top/exampleApp/Db/_APPNAME_Version.db new file mode 100644 index 000000000..1b03f08ba --- /dev/null +++ b/src/template/base/top/exampleApp/Db/_APPNAME_Version.db @@ -0,0 +1,6 @@ +record(lsi, "$(user):_APPNAME_:version") { + field(DTYP, "_APPNAME_ version") + field(DESC, "Version string") + field(SIZV, "$(SIZV=200)") + field(PINI, "YES") +} diff --git a/src/template/base/top/exampleApp/Db/dbVersionExample.db b/src/template/base/top/exampleApp/Db/dbVersionExample.db deleted file mode 100644 index e86b75dc4..000000000 --- a/src/template/base/top/exampleApp/Db/dbVersionExample.db +++ /dev/null @@ -1,7 +0,0 @@ -record(waveform, "$(user):version") { - field(DTYP, "Module Version") - field(DESC, "Module version") - field(FTVL, "CHAR") - field(NELM, "$(NELM=200)") - field(PINI, "YES") -} diff --git a/src/template/base/top/exampleApp/src/Makefile b/src/template/base/top/exampleApp/src/Makefile index 2a301d872..fa2a16ce7 100644 --- a/src/template/base/top/exampleApp/src/Makefile +++ b/src/template/base/top/exampleApp/src/Makefile @@ -14,21 +14,22 @@ DBDINC += xxxRecord # Install devXxxSoft.dbd into /dbd DBD += xxxSupport.dbd -# Compile and add the code to the support library +# Compile and add code to the support library _APPNAME_Support_SRCS += xxxRecord.c _APPNAME_Support_SRCS += devXxxSoft.c -_APPNAME_Support_SRCS += devGenVersion.c # Link locally-provided code into the support library, -# rather than directly into the IOC application. +# rather than directly into the IOC application, that +# causes problems on Windows DLL builds _APPNAME_Support_SRCS += dbSubExample.c +_APPNAME_Support_SRCS += dev_APPNAME_Version.c _APPNAME_Support_SRCS += _APPNAME_Hello.c _APPNAME_Support_SRCS += initTrace.c _APPNAME_Support_LIBS += $(EPICS_BASE_IOC_LIBS) -# Generate a header which defines a macro with a version string -# with the date and time, or a revision id from VCS system if available +# Auto-generate a header file containing a version string. +# Version comes from the VCS if available, else date+time. GENVERSION = _APPNAME_Version.h # Macro name GENVERSIONMACRO = _APPNAME_VERSION @@ -44,6 +45,7 @@ DBD += _APPNAME_.dbd _APPNAME__DBD += base.dbd _APPNAME__DBD += xxxSupport.dbd _APPNAME__DBD += dbSubExample.dbd +_APPNAME__DBD += dev_APPNAME_Version.dbd _APPNAME__DBD += _APPNAME_Hello.dbd _APPNAME__DBD += initTrace.dbd diff --git a/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd b/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd index 47f187050..64eb0389a 100644 --- a/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd +++ b/src/template/base/top/exampleApp/src/_APPNAME_Hello.dbd @@ -1,2 +1 @@ registrar(helloRegister) -device(waveform,INST_IO,devWfMyModVersion,"Module Version") diff --git a/src/template/base/top/exampleApp/src/devGenVersion.c b/src/template/base/top/exampleApp/src/devGenVersion.c deleted file mode 100644 index 297b69138..000000000 --- a/src/template/base/top/exampleApp/src/devGenVersion.c +++ /dev/null @@ -1,56 +0,0 @@ -/* devGenVersion.c */ -/* Example device support providing the module version string as a charactor array (long string) */ - -#include -#include -#include -#include - -#include "recGbl.h" -#include "alarm.h" -#include "recSup.h" -#include "devSup.h" -#include "menuFtype.h" -#include "waveformRecord.h" - -#include "_APPNAME_Version.h" - -/* must be last include */ -#include "epicsExport.h" - -static long read_wf(waveformRecord *prec) -{ - size_t N = strlen(_APPNAME_VERSION)+1; - char *buf = prec->bptr; - - if(prec->ftvl!=menuFtypeCHAR) { - (void)recGblSetSevr(prec, READ_ALARM, INVALID_ALARM); - return 0; - } - - if(N>=prec->nelm) - N = prec->nelm; - prec->nord = N; - - memcpy(buf, _APPNAME_VERSION, N); - buf[prec->nelm-1] = '\0'; - - return 0; -} - -static struct { - long number; - DEVSUPFUN report; - DEVSUPFUN init; - DEVSUPFUN init_record; - DEVSUPFUN get_ioint_info; - DEVSUPFUN read_si; -}devWfMyModVersion={ - 5, - NULL, - NULL, - NULL, - NULL, - read_wf, -}; -epicsExportAddress(dset,devWfMyModVersion); diff --git a/src/template/base/top/exampleApp/src/dev_APPNAME_Version.c b/src/template/base/top/exampleApp/src/dev_APPNAME_Version.c new file mode 100644 index 000000000..4f2c28f67 --- /dev/null +++ b/src/template/base/top/exampleApp/src/dev_APPNAME_Version.c @@ -0,0 +1,38 @@ +/* dev_APPNAME_Version.c */ +/* Example device support for the lsi (long string input) record + * providing the module version string as the value + */ + +#include +#include +#include + +#include "devSup.h" +#include "lsiRecord.h" + +#include "_APPNAME_Version.h" + +/* must be last include */ +#include "epicsExport.h" + +const char const version[] = _APPNAME_VERSION; + +static long read_string(lsiRecord *prec) +{ + size_t N = sizeof version; + char *buf = prec->val; + + if (N > prec->sizv) + N = prec->sizv; + prec->len = N; + + memcpy(buf, version, N); + buf[N - 1] = '\0'; + + return 0; +} + +static lsidset dev_CSAFEAPPNAME_Version = { + 5, NULL, NULL, NULL, NULL, read_string +}; +epicsExportAddress(dset,dev_CSAFEAPPNAME_Version); diff --git a/src/template/base/top/exampleApp/src/dev_APPNAME_Version.dbd b/src/template/base/top/exampleApp/src/dev_APPNAME_Version.dbd new file mode 100644 index 000000000..67295f3f0 --- /dev/null +++ b/src/template/base/top/exampleApp/src/dev_APPNAME_Version.dbd @@ -0,0 +1 @@ +device(lsi,INST_IO,dev_CSAFEAPPNAME_Version,"_APPNAME_ version") diff --git a/src/template/base/top/exampleBoot/ioc/st.cmd@Common b/src/template/base/top/exampleBoot/ioc/st.cmd@Common index c4eb081ba..a2d018e3a 100644 --- a/src/template/base/top/exampleBoot/ioc/st.cmd@Common +++ b/src/template/base/top/exampleBoot/ioc/st.cmd@Common @@ -13,7 +13,7 @@ _CSAFEAPPNAME__registerRecordDeviceDriver pdbbase ## Load record instances dbLoadTemplate "db/user.substitutions" -dbLoadRecords "db/dbVersionExample.db", "user=_USER_" +dbLoadRecords "db/_APPNAME_Version.db", "user=_USER_" dbLoadRecords "db/dbSubExample.db", "user=_USER_" ## Set this to see messages from mySub diff --git a/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS b/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS index 7b6319608..cc96f84ab 100644 --- a/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS +++ b/src/template/base/top/exampleBoot/ioc/st.cmd@RTEMS @@ -11,7 +11,7 @@ _CSAFEAPPNAME__registerRecordDeviceDriver(pdbbase) ## Load record instances dbLoadTemplate("db/user.substitutions") -dbLoadRecords("db/dbVersionExample.db", "user=_USER_") +dbLoadRecords("db/_APPNAME_Version.db", "user=_USER_") dbLoadRecords("db/dbSubExample.db", "user=_USER_") ## Set this to see messages from mySub diff --git a/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks b/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks index d8a2077ce..44a9afc67 100644 --- a/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks +++ b/src/template/base/top/exampleBoot/ioc/st.cmd@vxWorks @@ -20,7 +20,7 @@ _CSAFEAPPNAME__registerRecordDeviceDriver pdbbase ## Load record instances dbLoadTemplate "db/user.substitutions" -dbLoadRecords "db/dbVersionExample.db", "user=_USER_" +dbLoadRecords "db/_APPNAME_Version.db", "user=_USER_" dbLoadRecords "db/dbSubExample.db", "user=_USER_" ## Set this to see messages from mySub From 8b3d37d3925fcec0abc0b8539724381c9e98c1c3 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 10 Jul 2015 14:19:44 -0400 Subject: [PATCH 15/15] genVersionHeader: work with git repo w/o tags --always is necessary for (new) repositories w/o any tags. --abbrev=20 to get more than the default 7 characters of the hash --- src/tools/genVersionHeader.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl index f078ad4f6..5851ea831 100644 --- a/src/tools/genVersionHeader.pl +++ b/src/tools/genVersionHeader.pl @@ -72,7 +72,7 @@ if (!$vcs && -d "$opt_t/.git") { # Git # v1-4-abcdef-dirty # is 4 commits after tag 'v1' with short hash abcdef # with uncommited modifications - my $result = `git describe --tags --dirty`; + my $result = `git describe --always --tags --dirty --abbrev=20`; chomp $result; print "== git describe:\n$result\n==\n" if $opt_v; if (!$? && $result ne '') {