views:

288

answers:

1

I have a file system containing directories of "builds", each of which contains a file called "build-info.xml". However some of the builds happened before the build script generated "build-info.xml" so in that case I have a somewhat non-trivial SCons SConstruct that is used to generate a skeleton build-info.xml so that it can be used as a dependency for further rules.

I.e.: for each directory:

  • if build-info.xml already exists, do nothing. More importantly, do not remove it on a 'scons --clean'.
  • if build-info.xml does not exist, generate a skeleton one instead - build-info.xml has no dependencies on any other files - the skeleton is essentially minimal defaults.
  • during a --clean, remove build-info.xml if it was generated, otherwise leave it be.

My SConstruct looks something like this:

def generate_actions_BuildInfoXML(source, target, env, for_signature):
    cmd = "python '%s/bin/create-build-info-xml.py' --version $VERSION --path . --output ${TARGET.file}" % (Dir('#').abspath,)
    return cmd

bld = Builder(generator = generate_actions_BuildInfoXML, chdir = 1)
env.Append(BUILDERS = { "BuildInfoXML" : bld })

...

# VERSION = some arbitrary string, not important here
# path = filesystem path, set elsewhere
build_info_xml = "%s/build-info.xml" % (path,)
if not os.path.exists(build_info_xml):
    env.BuildInfoXML(build_info_xml, None, VERSION = build)

My problem is that 'scons --clean' does not remove the generated build-info.xml files.

I played around with env.Clean(t, build_info_xml) within the 'if' but I was unable to get this to work - mainly because I could not work out what to assign to 't' - I want a generated build-info.xml to be cleaned unconditionally, rather than based on the cleaning of another target, and I wasn't able to get this to work.

If I tried a simple env.Clean(None, "build_info_xml") after but outside the 'if' I found that SCons would clean every single build-info.xml file including those that weren't generated. Not good either.

What I'd like to know is how SCons goes about determining which files should be cleaned and which should not. Is there something funny about the way I've used a generator function that prevents SCons from recording this target as a Clean candidate?

+3  A: 

Ok, I think I've worked out what's going on - I made an incorrect assumption that SCons records those files it creates (as targets) and then uses this recorded list during a subsequent 'clean'. This of course makes no sense.

What SCons actually does is re-run through all the dependency rules and create a fresh dependency tree. It uses this to determine which files to clean. Because I had that os.path.exists() condition, it means that build-info.xml was never added to the Clean list because it would always exist at the time --clean is run.

It turns out that the env.Clean() was working properly, in that it would remove all such files, simply because there is no way for SCons when running the second time (with --clean) to know that a particular build-info.xml file was generated rather than already present.

The way to work around this would be to create a sentinel file alongside those generated files. But for now, my new understanding of SCons' Clean behaviour will suffice.

meowsqueak
This is a good description of the behavior. Thanks!
Dave Bacher