7
votes

I would like SCons to generate some source files for me in my src/ directory, and then build them as any other source file in my build directory build/variantX.

This is my SCons file:

import SCons

def my_builder(env, target, source):
    # do stuff
    pass

env = Environment()
env.VariantDir('build/variant1/', 'src', duplicate=0)
env.Command('src/foobar.cc', 'src/foobar.input', action=my_builder)
env.Program('bin/test', [
    'build/variant1/foobar.cc',
    'build/variant1/test.cc',
    ])

This errors with the following message:

Source src/foobar.cc not found, needed by target build/variant1/foobar.o

which I don't think is correct, considering that I am indeed providing a command to build src/foobar.cc.

Now, I tried a few workarounds:

  • if I replace build/variant1/foobar.cc in Program with src/foobar.cc, it does work, but obviously foobar.o gets created in src/ rather than build/variant1

  • if I replace src/foobar.cc in Command with build/variant1/foobar.cc, it does work, but I would like the code to be generated in src/; (also because things like relative paths in include directories won't work unless duplicate=1)

  • if duplicate=1, I get a similar error message, but this time mentioning the variant directory:

    Source build/variant1/foobar.cc not found, needed by target build/variant1/foobar.o

Is there a way around this? Is it a limitation/bug in SCons, or is there a fundamental misunderstanding on my side?

2
Did you ever find an answer to this problem? I'm facing something very similar. - jfritz42

2 Answers

2
votes

I would suggest creating an explicit dependency between the Command() and Program() calls as follows:

target1 = env.Command('src/foobar.cc', 'src/foobar.input', action=my_builder)
target2 = env.Program('bin/test', [
                      'build/variant1/foobar.cc',
                      'build/variant1/test.cc',
                      ])
Depends(target2, target1)
# This should work too
# Depends(target2, "src/foobar.cc")

Or you could specify the target from the Command() as part of the source for Program() as follows:

target1 = env.Command('src/foobar.cc', 'src/foobar.input', action=my_builder)
env.Program('bin/test', [
            target1,
            'build/variant1/test.cc',
            ])

I havent tested this, so Im not sure how it will work in conjunction with the call to VariantDir()

Here is some extra info regarding generating source code with SCons.

1
votes

I know it has been a while, but i hit the same wall. With minor modifications to the 'test case' and solution (see below) the code is:

import SCons

env = Environment()
env.VariantDir('build/variant1/', 'src', duplicate=0)
env.Command('src/foobar.cc', 'src/foobar.input', action="cp src/foobar.input src/foobar.cc", shell=True )
env.Depends("build/variant1/foobar.cc", "src/foobar.cc")
env.Program('bin/test', [
'build/variant1/foobar.cc',
])

The added 'env.Depends' on the 'variantdir-source' to 'generated-source' is the key. No idea why this is needed. I would call it a bug, but i guess its featured (based on the bug feedback you got .. )

Cheers,