Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In scons, how can I inject a target to be built?

Tags:

scons

I want to inject a "Cleanup" target which depends on a number of other targets finishing before it goes off and gzip's some log files. It's important that I not gzip early as this can cause some of the tools to fail.

How can I inject a cleanup target for Scons to execute?

e.g. I have targets foo and bar. I want to inject a new custom target called 'cleanup' that depends on foo and bar and runs after they're both done, without the user having to specify

% scons foo cleanup

I want them to type:

% scons foo

but have scons execute as though the user had typed

% scons foo cleanup

I've tried creating the cleanup target and appending to sys.argv, but it seems that scons has already processed sys.argv by the time it gets to my code so it doesn't process the 'cleanup' target that I manually append to sys.argv.

like image 754
Ross Rogers Avatar asked Apr 01 '09 22:04

Ross Rogers


3 Answers

you shouldn't use _Add_Targets or undocumented features, you can just add your cleanup target to BUILD_TARGETS:

from SCons.Script import BUILD_TARGETS
BUILD_TARGETS.append('cleanup')

if you use this documented list of targets instead of undocumented functions, scons won't be confused when doing its bookkeeping. This comment block can be found in SCons/Script/__init__.py:

# BUILD_TARGETS can be modified in the SConscript files.  If so, we
# want to treat the modified BUILD_TARGETS list as if they specified
# targets on the command line.  To do that, though, we need to know if
# BUILD_TARGETS was modified through "official" APIs or by hand.  We do
# this by updating two lists in parallel, the documented BUILD_TARGETS
# list, above, and this internal _build_plus_default targets list which
# should only have "official" API changes.  Then Script/Main.py can
# compare these two afterwards to figure out if the user added their
# own targets to BUILD_TARGETS.

so I guess it is intended to change BUILD_TARGETS instead of calling internal helper functions

like image 151
g_daniel Avatar answered Oct 20 '22 15:10

g_daniel


One way is to have the gzip tool depend on the output of the log files. For example, if we have this C file, 'hello.c':

#include <stdio.h>
int main()
{
    printf("hello world\n");
    return 0;
}

And this SConstruct file:

#!/usr/bin/python
env = Environment()
hello = env.Program('hello', 'hello.c')
env.Default(hello)
env.Append(BUILDERS={'CreateLog':
    Builder(action='$SOURCE.abspath > $TARGET', suffix='.log')})
log = env.CreateLog('hello', hello)
zipped_log = env.Zip('logs.zip', log)
env.Alias('cleanup', zipped_log)

Then running "scons cleanup" will run the needed steps in the correct order:

gcc -o hello.o -c hello.c
gcc -o hello hello.o
./hello > hello.log
zip(["logs.zip"], ["hello.log"])

This is not quite what you specified, but the only difference between this example and your requirement is that "cleanup" is the step that actually creates the zip file, so that is the step that you have to run. Its dependencies (running the program that generates the log, creating that program) are automatically calculated. You can now add the alias "foo" as follows to get the desired output:

env.Alias('foo', zipped_log)
like image 3
richq Avatar answered Oct 20 '22 17:10

richq


In version 1.1.0.d20081104 of SCons, you can use the private internal SCons method:

SCons.Script._Add_Targets( [ 'MY_INJECTED_TARGET' ] )

If the user types:

% scons foo bar 

The above code snippet will cause SCons to behave as though the user had typed:

% scons foo bar MY_INJECTED_TARGET
like image 1
Ross Rogers Avatar answered Oct 20 '22 16:10

Ross Rogers