user2821
user2821

Reputation: 1604

How can SCons detect changes in SConstruct script?

I want build files based on variables that are assigned in the SConstruct file. As in this example:

import os

env  = Environment(ENV = os.environ)

def text_file_maker(target, source, env):
    with open(str(target[0]), "w") as text_file:
        text_file.write(env['my_text'])
    return 0


env.Append( BUILDERS = {'Make_text' : Builder(action = text_file_maker)})


env.Make_text(target = 'sour.txt', 
    source = None, 
    my_text = 'lemon')


env.Make_text(target = 'sweet.txt', 
    source = None, 
    my_text = 'apple')

Running this script generates two text files with the content 'lemon' and 'apple'. If I'm running the script again, SCons correctly detects that the targets exist:

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.

Now if I'm changing one target, e.g:

env.Make_text(target = 'sweet.txt', 
    source = None, 
    my_text = 'orange')

and run the script, I'll get scons: '.' is up to date. and the content 'orange' is not written to sweet.txt.

I could specify a dependency:

Depends(['sweet.txt', 'sour.txt'], 'SConstruct')

but that forces a rebuild for any change in my SConstruct script.

How can I make SCons recognise changes in the SConstruct script that affects the targets?

This could be a very simple question, sorry if I missed something obvious.

Upvotes: 2

Views: 620

Answers (1)

bdbaddog
bdbaddog

Reputation: 3509

You're example very closely resembles the answer which is in the manpage (Search for "Action Objects"):

https://scons.org/doc/production/HTML/scons-man.html

The third and succeeding arguments, if present, may either be a construction variable or a list of construction variables whose values will be included in the signature of the Action when deciding whether a target should be rebuilt because the action changed. The variables may also be specified by a varlist= keyword parameter; if both are present, they are combined. This is necessary whenever you want a target to be rebuilt when a specific construction variable changes. This is not often needed for a string action, as the expanded variables will normally be part of the command line, but may be needed if a Python function action uses the value of a construction variable when generating the command line.

def build_it(target, source, env):
    # build the target from the 'XXX' construction variable
    open(target[0], 'w').write(env['XXX'])
    return 0

# Use positional arguments.
a = Action(build_it, '$STRINGIT', ['XXX'])

# Alternatively, use a keyword argument.
a = Action(build_it, varlist=['XXX'])

So in your case change:

env.Append( BUILDERS = {'Make_text' : Builder(action = text_file_maker)})

To

tfb_action = Action(text_file_maker, varlist=['my_text'])
env.Append( BUILDERS = {'Make_text' : Builder(action = tfb_action)})

Upvotes: 5

Related Questions