dev.nlited.com

>>

Version Information

2014-12-29 21:55:07 chip Page 1150 📢 PUBLIC

Version Information

Updating the version information automatically during every build is absolutely critical, especially when working with drivers. The first thing the driver should do when it loads is print out the build string. I cannot understate the amount of exasperation I have experienced simply because the wrong version of a driver was loaded.

VerID.h

This defines the version information structures. It never changes.

#ifndef __VERID_H__ #define __VERID_H__ 0x0101 struct VerNum_s { unsigned char Major; unsigned char Minor; unsigned short Build; }; struct VerID_s { struct VerNum_s File; struct VerNum_s Prod; const char *Builder; const char *BuildTime; const char *BuildStr; }; #ifdef __cplusplus extern "C" const struct VerID_s gVerID; #else extern const struct VerID_s gVerID; #endif #define VER_STR(S) #S #define VER_BUILDSTR(MJ,MN,BD,ID,SUF) VER_STR(MJ)"."VER_STR(MN)"."VER_STR(BD)" " SUF " [" ID "]" #endif /**EOF: VERID.H**/

VerProd.h

VerProd.h contains the reference version numbers for the entire product. It is updated during every release build.

/*************************************************************************/ /** VerProd.h: Version information for the NetMon product. **/ /** March 2013, Chip Doran **/ /** NOTE: This file is modified by VerUpdate.pl during every release **/ /** build. **/ /*************************************************************************/ #define VER_PROD_MAJOR 2 //Dec 14 2013: Adding FileMon #define VER_PROD_MINOR 0 //Dec 14 2013: Adding FileMon #define VER_PROD_BUILD 0 /**EOF: VERPROD.H**/

VerFile.h

VerFile.h contains the reference version numbers for each binary (.exe or .sys) file created. It is updated during every build.

/*************************************************************************/ /** VerFile.h: Version information for NetMod driver **/ /** NOTE: This file is modified automatically by VerUpdate.pl during **/ /** every build. **/ /*************************************************************************/ #define VER_FILE_MAJOR 2 //Dec 14 2013 Adding FileMon #define VER_FILE_MINOR 1 //Jan 04 2014 Stable version #define VER_FILE_BUILD 657 #ifndef VER_SUFFIX #define VER_SUFFIX "" #endif #define VER_BUILDER "VS12" #define VER_BUILD_TIME "20140105091611"

VerID.c

VerID.c is the source code that includes VerProd.h and VerFile.h. This is where the version information is instatiated. This file never changes, but is recompiled during every build in the PreLink step.

/*************************************************************************/ /** VerID.c: Definition of the version and build information. **/ /** May 2011, Chip Doran **/ /*************************************************************************/ #include "StdTypes.h" #include "VerID.h" #include "VerProd.h" #include "VerFile.h" const struct VerID_s gVerID= { { VER_FILE_MAJOR, VER_FILE_MINOR, VER_FILE_BUILD }, { VER_PROD_MAJOR, VER_PROD_MINOR, VER_PROD_BUILD }, VER_BUILDER, VER_BUILD_TIME, VER_BUILDSTR(VER_FILE_MAJOR,VER_FILE_MINOR,VER_FILE_BUILD,VER_BUILDER,VER_SUFFIX) }; /**EOF: VERID.C**/


VerUpdate.pl

VerUpdate.pl is the perl script that updates VerFile.h, VerProd.h, and the resource script (.rc).

############################################################################ ## VerUpdate.pl: Updates build info in VerFile.h and Resource.rc files ## ## Chip Doran ## ## May 2011: Initial version ## ## Jul 2012: Unicode support ## ############################################################################ use strict; use Encode; use File::stat; use POSIX qw(strftime); ############################################################################ ## Input files ## ## VerProd.h: Global to the entire product line. ## ## This file should contain (at least) these lines: ## ## #define VER_PROD_MAJOR 1 ## ## #define VER_PROD_MINOR 1 ## ## #define VER_PROD_BUILD 1 ## ## VerFile.h: For each executable, library, etc. ## ## This file should contain (at least) these lines: ## ## #define VER_FILE_MAJOR 1 ## ## #define VER_FILE_MINOR 0 ## ## #define VER_FILE_BUILD 2 ## ## Resource.rc: Windows Visual Studio resource script. ## ## The following lines will be updated to reflect VerProd.h, VerFile.h: ## ## FILEVERSION 1,0,0,0 ## ## PRODUCTVERSION 1,0,0,0 ## ## VALUE "FileVersion", "1,0,0,0" ## ## VALUE "ProductVersion", "1,0,0,0" ## ## VALUE "Builder", "$BuilderID" ## ## VALUE "BuildTime", "$BuildTime" ## ############################################################################ ############################################################################ ## Globals ## ############################################################################ our $DoProdIncr= 0; ##Do increment VerProd.h:BUILD? our $DoDebug= 0; ##Do print debug text? our $DoOverwrite= 1; ##Do rewrite input files? our $DoEcho= 0; ##Do echo file read/write? our $FileFName; ##VerFile.h file our $ProdFName= "; ##VerProd.h file our $ResourceFName; ##Resource.rc file our $ProdMajor= 1; ##Product version info our $ProdMinor= 0; our $ProdBuild= 0; our $FileMajor= 1; ##File version info our $FileMinor= 0; our $FileBuild= 0; our $BuildTime= strftime("%Y%m%d%H%M%S",localtime); our $BuilderID= $ENV{"COMPUTERNAME"}; ##Builder machine name our @Lines= (); ##Holds entire file, without newlines our $BOM; ##Set if not ASCII text. our $Encoding; ##Set to encoding name (UTF-16LE) our $NewLine= "rn"; ##Newline to be appended to each line ############################################################################ ## Command line arguments ## ############################################################################ foreach(@ARGV) { if(/^prod=(.*)/i) { $ProdFName= $1; } elsif(/^prodincr/i) { $DoProdIncr= 1; } elsif(/^builder=(.*)/i) { $BuilderID= $1; } elsif(/^resource=(.*)/i) { $ResourceFName= $1; } elsif(/^help/i) { DoHelp(); } elsif(/^debug/i) { $DoDebug= 1; } elsif(/^readonly/i) { $DoOverwrite= 0; } elsif(/^write/i) { $DoOverwrite= 1; } elsif(/^echo/i) { $DoEcho= 1; } else { $FileFName= $_; } } if($ProdFName) { print "Reading product info from $ProdFName...n"; ReadLines($ProdFName); $ProdMajor= UpdateBuildNumber("VER_PROD_MAJOR",0); $ProdMinor= UpdateBuildNumber("VER_PROD_MINOR",0); $ProdBuild= UpdateBuildNumber("VER_PROD_BUILD",$DoProdIncr); WriteLines($ProdFName); } if($FileFName) { print "Reading file info from $FileFName...n"; ReadLines($FileFName); UpdateBuilderID($BuilderID); $FileMajor= UpdateBuildNumber("VER_FILE_MAJOR",0); $FileMinor= UpdateBuildNumber("VER_FILE_MINOR",0); $FileBuild= UpdateBuildNumber("VER_FILE_BUILD",1); UpdateBuildTime(); WriteLines($FileFName); if($ResourceFName) { print "Updating resource script $ResourceFName...n"; UpdateResource(); } } print "DONEn" if $DoDebug; sub DoHelp { print "VerUpdate filename [debug] [prod=file.h] [builder=name] [resource=project.rc]n"; print "Updates version information.n"; print " debug Enables verbose outputn"; print " prod=file Read product version from filen"; print " prodincr Increment product buildn"; print " builder=name Set Builder namen"; print " resource=file Update resource script's version blockn"; print " help Display usage helpn"; print " readonly Write output files to .newn"; print " echo Print files as read and written.n"; exit; } ############################################################################ ## Determine the Unicode encoding by reading the BOM (Byte Order Marker) ## ## from the first 2 bytes of the file. ## ## Currently only supports UTF-16LE (0xFEFF) (Windows default). ## ## Everything else is assumed to be 8bit ASCII. ## ############################################################################ sub GetEncoding { my $FName= shift(@_); open(FILE,"<:raw",$FName) or die "Unable to get encoding for $FName.n"; binmode(FILE); $BOM= unpack('S!',substr(,0,2)); if($BOM==0xFEFF) { printf("BOM[%04X] Using UTF-16LEn",$BOM) if $DoDebug; $Encoding= 'UTF-16LE'; $NewLine= encode($Encoding,"rn"); } else { printf("BOM[%04X] Assuming ASCIIn",$BOM) if $DoDebug; $Encoding= 0; $BOM= 0; } close(FILE); } ############################################################################ ## Read the entire file into the @Lines array. ## ## Dealing with Unicode, BOM, and CRLF is a real PitA with perl! ## ############################################################################ sub ReadLines { my $FName= shift(@_); @Lines= (); printf("Reading '%s'n",$FName) if $DoDebug; GetEncoding($FName); if($BOM) { ReadLinesUnicode($FName); } else { ReadLinesAscii($FName); } chomp(@Lines); } #Reading a Unicode file. #The entire file needs to be read in RAW mode, decoded, then split into lines. #Otherwise, perl messes up the 0D0A sequences and garbles the unicode. sub ReadLinesUnicode { my $FName= shift(@_); my $ContentRaw; my $ContentDec; open(FILE,"<:raw",$FName) or die "Unable to open '$FName' for reading.n"; $ContentRaw= do { local $/; }; close(FILE); $ContentDec= decode($Encoding,$ContentRaw); @Lines= split("rn",$ContentDec); } sub ReadLinesAscii { my $FName= shift(@_); open(FILE,"<",$FName) or die "Unable to open '$FName' for reading.n"; while() { print "$_" if $DoEcho; push(@Lines,$_); } close(FILE); } ############################################################################ ## Write the entire @Lines array back out to the file. ## ############################################################################ sub WriteLines { my $FName= shift(@_); $FName= $FName.".new" if !$DoOverwrite; print "Writing $FName using '$Encoding'n" if $DoDebug; print "------n" if $DoDebug; ClearReadOnly($FName); if($BOM) { WriteLinesUnicode($FName); } else { WriteLinesAscii($FName); } } #Writing a Unicode file. #The file needs to be written in RAW mode, otherwise the CRLF's will be #all messed up. The NewLine needs to be encoded before being written. #The BOM needs to be updated after the file has been written. sub WriteLinesUnicode { my $FName= shift(@_); my $ContentDec; open(FILE,">:raw",$FName) or die "Unable to open '$FName' for writing.n"; foreach(@Lines) { print FILE encode($Encoding,$_).$NewLine; } close(FILE); printf("Writing BOM[%04X]n",$BOM) if $DoDebug; open(FILE,"+<:raw",$FName); binmode(FILE); print FILE pack('S!',$BOM); close(FILE); } sub WriteLinesAscii { my $FName= shift(@_); open(FILE,">",$FName) or die "Unable to open '$FName' for writing.n"; foreach (@Lines) { print "$_n" if $DoEcho; print FILE "$_n"; } close(FILE); } ############################################################################ ## Clear the ReadOnly flag for both Windows and Linux. ## ############################################################################ sub ClearReadOnly { my $FName= shift(@_); my $Attr= stat($FName); if(-r $FName) { printf("$FName attribute: %xn",$Attr->mode) if $DoDebug; print "$FName: Enable Writesn" if $DoDebug; chmod($Attr->mode|0222,$FName); } } ############################################################################ ## Find and increment the builder number ## ## This is performed on the @Lines array. ## ############################################################################ sub UpdateBuildNumber { my $Token= shift(@_); my $DoIncr= shift(@_); my $IsFound= 0; my $BuildID= 0; foreach (@Lines) { if(/^#define $Token(s+?)([0-9]+)(.*)/) { $BuildID= $2+$DoIncr; $_= "#define $Token$1$BuildID$3"; print "Found: $_n" if $DoDebug; $IsFound= 1; } } if(!$IsFound) { $BuildID= $DoIncr; print "$Token not found.n"; $Lines[$#Lines]= "#define $Token $BuildID"; } return($BuildID); } #Find and set the VER_BUILDER ident. sub UpdateBuilderID { my $Builder= shift(@_); my $IsFound= 0; foreach (@Lines) { if(/^#define VER_BUILDER(s+?)"([^"])*"(.*)/) { $_= "#define VER_BUILDER$1"$Builder"$3"; print "Found: $_n" if $DoDebug; $IsFound= 1; } } if(!$IsFound) { print "VER_BUILDER not found.n"; $Lines[$#Lines]= "#define VER_BUILDER "$Builder""; } } #Find and set the VER_BUILD_TIME line. sub UpdateBuildTime { my $IsFound= 0; foreach(@Lines) { if(/^#define VER_BUILD_TIME(s+?)"([^"])*"(.*)/) { $_= "#define VER_BUILD_TIME$1"$BuildTime"$3"; print "Found: $_n" if $DoDebug; $IsFound= 1; } } if(!$IsFound) { print "VER_BUILD_TIME not found.n"; $Lines[$#Lines]= "#define VER_BUILD_TIME "$BuildTime""; } } ############################################################################ ## Resource Script ## ## Update the version information in a resource script to match. ## ############################################################################ sub UpdateResource { my $IsUpdate; ReadLines($ResourceFName); foreach(@Lines) { $IsUpdate= 1; if(/^( *)(FILEVERSION) */) { $_= "$1$2 $FileMajor,$FileMinor,0,$FileBuild"; } elsif(/^( *)(PRODUCTVERSION) */) { $_= "$1$2 $ProdMajor,$ProdMinor,0,$ProdBuild"; } elsif(/^( *)(VALUE "FileVersion",)/i) { $_= "$1$2 "$FileMajor,$FileMinor,0,$FileBuild""; } elsif(/^( *)(VALUE "ProductVersion",)/i) { $_= "$1$2 "$ProdMajor,$ProdMinor,0,$ProdBuild""; } elsif(/^( *)(VALUE "Builder",)/i) { $_= "$1$2 "$BuilderID""; } elsif(/^( *)(VALUE "BuildTime",)/i) { $_= "$1$2 "$BuildTime""; } else { $IsUpdate= 0; } print "UPDATE: $_n" if $IsUpdate && $DoDebug; } ClearReadOnly($ResourceFName); WriteLines($ResourceFName); } #/**EOF: VerUpdate.pl**/


WebV7 (C)2018 nlited | Rendered by tikope in 36.417ms | 3.145.58.162