Delphi pre-build event not executing BEFORE compile
I'm busy automating our builds to include the svn revision number. We're using Delphi 2010. I added a pre-build event calling a batch file that injects the the svn revision number (read from the entries file in the .svn directory) and a specified version number into aVersionInfo.rc that is compiled with my project. The pre-build event looks like this:
call SetVersionInfo.bat 6 5 4
...and the batch file (hope someone finds this useful)...
@ECHO OFF
SETLOCAL
setLocal EnableDelayedExpansion
SET _myVar=0
FOR /F %%G in (.svn\entries.) DO (
IF !_myVar! LSS 3 SET /A _myVar+=1 & SET _svn_dir_rev=%%G
)
ECHO 1 VERSIONINFO > aVersionInfo.rc
ECHO. FILEVERSION %1,%2,%3,%_svn_dir_rev% >> aVersionInfo.rc
ECHO. PRODUCTVERSION 1 >> aVersionInfo.rc
ECHO. FILEOS VOS__WINDOWS32 >> aVersionInfo.rc
ECHO. FILETYPE VFT_APP >> aVersionInfo.rc
ECHO. BEGIN >> aVersionInfo.rc
ECHO. BLOCK "StringFileInfo" >> aVersionInfo.rc
ECHO. BEGIN >> 开发者_如何学PythonaVersionInfo.rc
ECHO. BLOCK "080904b0" >> aVersionInfo.rc
ECHO. BEGIN >> aVersionInfo.rc
ECHO. VALUE "CompanyName","COMPANY\000" >> aVersionInfo.rc
ECHO. VALUE "FileDescription","APP\000" >> aVersionInfo.rc
ECHO. VALUE "FileVersion","%1.%2.%3.%_svn_dir_rev%\000" >> aVersionInfo.rc
ECHO. VALUE "InternalName","APP\000" >> aVersionInfo.rc
ECHO. VALUE "LegalCopyright","Copyright APP\000" >> aVersionInfo.rc
ECHO. VALUE "LegalTrademarks","APP\000" >> aVersionInfo.rc
ECHO. VALUE "OriginalFilename","APP.exe\000" >> aVersionInfo.rc
ECHO. VALUE "ProductName","APP\000" >> aVersionInfo.rc
ECHO. VALUE "ProductVersion,"1\000" >> aVersionInfo.rc
ECHO. VALUE "Comments","Compiled on %date% by %username%\000" >> aVersionInfo.rc
ECHO. END >> aVersionInfo.rc
ECHO. END >> aVersionInfo.rc
ECHO. BLOCK "VarFileInfo" >> aVersionInfo.rc
ECHO. BEGIN >> aVersionInfo.rc
ECHO. VALUE "Translation", 0x0809 1200 >> aVersionInfo.rc
ECHO. END >> aVersionInfo.rc
ECHO. END >> aVersionInfo.rc
ENDLOCAL
The batch file does execute as part of a compile, aVersionInfo.rc is updated, aVersionInfo.res is recompiled, but for some reason the new res file is not used to compile the exe. It is, however, updated during a clean build or if I compile a second time. It seems the check for changes to the rc files takes place before the "pre"-build events are called. Which actually makes it a mid-build event. Or am I missing something?
I did try deleting the aVersionInfo.res file as another pre-build event, but then the compiler complains that this file is missing. Could it be that the
{$R 'aVersionInfo.res' 'aVersionInfo.rc'}
line is in the wrong place?
Try using
{$R aVersionInfo.res}
and calling brcc32 aVersionInfo.rc
manually from your batch file (after you're done with creating the .rc file). That way your .res file should be excluded from the normal IDE build.
May be is missing a ["]
ECHO. VALUE "ProductName","APP\000" >> aVersionInfo.rc
ECHO. VALUE "ProductVersion,"1\000" >> aVersionInfo.rc
------- HERE -----------------------^
ECHO. VALUE "Comments","Compiled on %date% by %username%\000" >> aVersionInfo.rc
Bye
TL;DR:
Place the line {$R 'aVersionInfo.res' 'aVersionInfo.rc'}
directly below the Program statement once, then build. Or use BRCC32 to force the first time build of the .RES file
Long version:
Your guess that the line:
{$R 'aVersionInfo.res' 'aVersionInfo.rc'}
is in the wrong place is partially correct.
When I initially set up using an .RC file under Delphi XE2, I had the same trouble with slightly different code, sometimes compiling and sometimes not. I tried variations like:
{$R 'aVersionInfo.res' 'aVersionInfo.rc'}
{$R '.\aVersionInfo.res' '.\aVersionInfo.rc'}
but the XE2 compiler kept complaining about the RES file not being found, if indeed it was not there (note that this was my initial build).
It turns out you first have to place that line directly below the Program statement:
program TTClient;
{$R 'VersionInfo.res' 'VersionInfo.rc'}
... and not in the vicinity of your already present
{$R *.res}
Then you build your program once.
After that you can move the line back to a more logical place:
{$R *.res}
{$R 'VersionInfo.res' 'VersionInfo.rc'}
For some weird reason, once Delphi 'knows' that the .rc file is part of the project, it no longer matters if you either:
- place the line anywhere else
- have a .res file present or not
No need for a precompile step. If the .RC file is modified, the compiler will rebuild the .RES file, whether an earlier version existed or not.
This weird behavior does not really help when you set up this system initially ;-(
There are other strange things going on with the parsing of the project source and the construction of the .dproj file which brought me to this solution, notably:
If you rename the .rc file, this may get you into trouble again: There are remnants in the .dproj file still pointing to the old .rc file and the compiler will complain about not finding it. You have to edit this old name out of the .dproj file to fix this.
Note this was all under XE2, under other version YMMV.
Edited to add: You may still have to battle with XE2 Version Info Not Working issue.
Add a line to your batch file that modifies the Delphi source file that includes the resource:
touch VersionInfo.pas
Then the source file should get recompiled. If the source file isn't modified, then there's no reason for the compiler to re-link that portion of the program, and so the updated resource file won't be noticed.
You could call brcc32 inside the batch file so it will always update the .res file. I do something similar and it works in a compile as well as a build.
精彩评论