开发者

How to make SCONS update the contents of a file used in a build

What's the proper SCONS method for updating the contents of a file that is part of build?

I use SCONS to build a fairly large project. But for the sake of a simple question, assume it looks like this:

env.Program("foo", ["foo.c", "version.c"])

Under certain build conditions, it's necessary to update the contents of one of the CPP files in the build with new information - version information actually. In the above example, I would need to modify the contents of "version.c". I thought I could do this rather nicely with the following example:

env.Command(target="version.c", source=[], action=PythonFunctionToUpdateContents)
env.Program("foo", ["foo.c", "version.c"])

The PythonFunctionToUpdateContents would use开发者_StackOverflow中文版 target[0] as the name of the file, open it, look for some specific text, change it, write the changes back to the same file. Unfortunately, the above sample doesn't work. SCONS automatically deletes a target file before building it, so my "version.c" file got deleted before it could be updated.

I tried setting the target and source to the same file in the env.Command() call, but that just creates a dependency cycle.

I know that I could solve this by having SCONS generate the ENTIRE version.c file, but that's not suitable since version.c contains a lot of other code that can change as part of normal development.


The usual way to do this is to have a "version.c.in" or "version-in.c" or whatever you like to call it. Modify that and output it to version.c. You would add the "in" file to your version control system, while the version.c file would not be in there. So the result of all this would look as follows:

env.Command(target="version.c", source="version-in.c",
            action=PythonFunctionToUpdateContents)
env.Program("foo", ["foo.c", "version.c"])

This applies to other build systems too - it is generally a bad idea to have an input file also be an output file. Far better to use an intermediate file to get the job done.


This answer is kinda late to the party, but here it is anyway:

You should use env.Precious("version.c"). This prevents the file from being deleted before being built.

You probably also want to use env.NoClean("version.c") so that it doesn't get deleted during a clean.

You COULD use env.SideEffect maybe, but that one seems to have a couple weird things about it. I was told on the mailing list to generally not use that one.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜