问题
I have a requirement to generate version.cc file from SCons Script. This file should be generated only if any of the source file for a target has changed.
Suppose the SCons script has the following statements
#python function which generates version.cc in the same folder where libtest.a is generated. This will always generate a differnt version.cc because the version string contained inside that will have timestamp
GenerateVersionCode()
#target which uses version.cc
libtest = env.Library('test', ['a.cc', 'b.cc', 'version.cc'])
First time when I run the above code everything is fine. But when I run the same script again, the target 'test' will be rebuilt because of new version.cc which got generated. My requirement is we should not generate new version of version.cc file if the file is already present and there are no changes in any of the sources (namely a.cc and b.cc in this example)
if not version_file_present: GenerateVersionCode() else if no_changes_in_source: GenerateVersionCode() #target which uses version.cc which could be newly generated one or previous one libtest = env.Library('test', ['a.cc', 'b.cc', 'version.cc'])
One related question on this site suggested something as follows
env.Command(target="version.c", source="version-in.c", action=PythonFunctionToUpdateContents) env.Program("foo", ["foo.c", "version.c"])
W.r.to the above suggestion I would want to know the contents of function PythonFunctionToUpdateContents which checks the change in source files since previous build.
回答1:
As I understand it, you only want to generate version.cc if any of the source files change, and you only want to build the library if version.cc changes or if any of the library source files change. That is, consider version.cc as one of the source files for the library.
If this is the case, you could consider 2 sets of dependencies, both of which would be controlled by the SCons dependency checking.
Its not real clear what the version.cc generation consists of, but lets assume that the python function GenerateVersionCode() will do exactly that: generate version.cc, but wont have any dependency checking related logic.
Here is the SConscript code:
def GenerateVersionCode(env, target, source):
# fill in generation code here
# The version.cc checking
env.Command(target='version.cc',
source=['a.cc', 'b.cc'],
action=GenerateVersionCode)
# The library
env.Library(target='test', source=['version.cc', 'a.cc', 'b.cc'])
It shouldnt be necessary, but this could be taken one step further by explicitly setting a dependency from the Library target to the version.cc target with the SCons Depends() function.
Here is the output I get when I build, and instead of using the GenerateVersionCode() function, I use a simple shell script versionGen.sh, thus changing the call to Command() to this:
env.Command(target='version.cc',
source=['a.cc', 'b.cc'],
action='./versionGen.sh')
Here is the first build:
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o a.o -c a.cc
g++ -o b.o -c b.cc
./versionGen.sh
g++ -o version.o -c version.cc
ar rc libtest.a version.o a.o b.o
ranlib libtest.a
scons: done building targets.
Then, without having changed anything, I build again, and it does nothing:
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
Then, I modify a.cc, and build again, and it generates a new version of version.cc:
> vi a.cc
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o a.o -c a.cc
./versionGen.sh
g++ -o version.o -c version.cc
ar rc libtest.a version.o a.o b.o
ranlib libtest.a
scons: done building targets.
来源:https://stackoverflow.com/questions/17327300/scons-generating-version-file-only-if-target-has-changed