Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SCons code generation and VariantDir

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?

like image 591
UncleZeiv Avatar asked May 14 '13 14:05

UncleZeiv


People also ask

Why do SCons use src_Dir instead of variant_Dir?

This will cause scons to invoke Builders using the path names of source files in src_dir and the path names of derived files within variant_dir. This is always more efficient than the default duplicate=1, and is usually safe for most builds (but see above for cases that may cause problems).

How does variantdir() work?

Note that VariantDir () works most naturally with a subsidiary SConscript file. However, you would then call the subsidiary SConscript file not in the source directory, but in the variant directory, regardless of the value of duplicate. This is how you tell scons which variant of a source tree to build. For example:

How do I specify a variant directory for a sconscript file?

See also the SConscript () function for another way to specify a variant directory in conjunction with calling a subsidiary SConscript file. Use the VariantDir () function to establish that target files should be built in a separate directory from the source files:

How do I disable duplicates of source files in variantdir?

When using the VariantDir function directly, SCons still duplicates the source files in the variant directory by default: You can specify the same duplicate=0 argument that you can specify for an SConscript () call: In which case SCons will disable duplication of the source files:


2 Answers

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.

like image 111
Brady Avatar answered Nov 24 '22 09:11

Brady


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,

like image 34
susundberg Avatar answered Nov 24 '22 09:11

susundberg