Scons Cyclic Dependency

879 views Asked by At

We updated from scons 2.4.1 to 2.5.1 and suddenly get several errors like so: scons: *** Found dependency cycle(s): Internal Error: no cycle found for node ...

The issue I believe pertains to a version file that we attempt to automatically update if our SCM detects an edit to source files. The gist of the process is that we maintain a file 'version.cfg' that has #defines. This file is checked into our SCM. If the file has already been updated once, it will not be updated a second time until the file is commited to the SCM. This file is then used to autogenerate a C++ header file named 'kb_version.hh'.

What is the cyclic dependency and how can I eliminate it? (note, whatever the issue is, did not cause problems in scons 2.4.1 (only if we use the new version 2.5.1 does it detect the cyclic dependency).

The relevant scons snippet is below:

 SRCDIR = '../../src'

 SRCS = [
   'kb.cc',
 ]

 SOURCE = [ os.path.join(SRCDIR, s) for s in SRCS ]

 SCRIPT_VERSION_GEN = os.path.join(env['_ROOT'], 'kb/build/scripts/versionGen.sh')
 SCRIPT_VERSION_UPD = os.path.join(env['_ROOT'], 'kb/build/scripts/versionUpdate.sh')

 FILE_VERSION_CFG = 'version.cfg'
 FILE_VERSION_HH  = 'kb_version.hh'

 scriptVerGen = env.File(SCRIPT_VERSION_GEN)
 scriptVerUpd = env.File(SCRIPT_VERSION_UPD)
 verCfg = env.File(os.path.join(SRCDIR, FILE_VERSION_CFG))
 verHH  = env.File(os.path.join(SRCDIR, FILE_VERSION_HH))

 ## this command detects for change in source files, then updates, when necessary, the source version.cfg
 env.Command(
   target = verCfg,
   source = [ SOURCE, scriptVerUpd ],
   action = [ scriptVerUpd.path + ' ' + env['BS_DIR_SRCROOT'] + '/kb/foo' + verCfg.srcnode().path, Copy(verCfg.path, verCfg.srcnode().path) ]
 )

 env.Command(
   target = verHH,
   source = [ verCfg, scriptVerGen ],
   action = scriptVerGen.path + ' ' + verHH.path + ' ' + verCfg.path
 )
2

There are 2 answers

0
rkemp On BEST ANSWER

I was able to track down the problem, though I am not sure if this is desirable behavior from scons.

The issue is this. (1) C++ source file depends on version.h (by way of #include) (2) version.h is autogenerated from version.cfg (3) version.cfg is auto-incremented if any source file has been updated, which includes source files that depend on version.h (thus the cyclic dependency). However, no actual change might happen to the c++ source file, but the file itself #includes version.h. So our intent is that if and only if the source file itself has changed, then version.cfg should be updated (not the object file that results from compiling the source file).

In the comment below, the cyclic depency can be eliminated by removing the SOURCE variable from the "source = " line in the first env.Command() call.

Is there a way in scons to say I depend on the source file, but not the object file? Or is this a bug/nuance in the cyclic dependency?

8
bdbaddog On

A few inline questions. Not easy to do in comments section above.. (See ## comments below)

 SRCDIR = '../../src'

 SRCS = [
   'kb.cc',
 ]

 SOURCE = [ os.path.join(SRCDIR, s) for s in SRCS ]


 ## Is _ROOT the top of your tree where SConstruct lives?
 SCRIPT_VERSION_GEN = os.path.join(env['_ROOT'], 'kb/build/scripts/versionGen.sh')
 SCRIPT_VERSION_UPD = os.path.join(env['_ROOT'], 'kb/build/scripts/versionUpdate.sh')

 FILE_VERSION_CFG = 'version.cfg'
 FILE_VERSION_HH  = 'kb_version.hh'

 scriptVerGen = env.File(SCRIPT_VERSION_GEN)
 scriptVerUpd = env.File(SCRIPT_VERSION_UPD)
 verCfg = env.File(os.path.join(SRCDIR, FILE_VERSION_CFG))
 verHH  = env.File(os.path.join(SRCDIR, FILE_VERSION_HH))

 ## this command detects for change in source files, then updates, when necessary, the source version.cfg
 env.Command(
   target = verCfg,
   source = [ SOURCE, scriptVerUpd ],

   ## Why not do this?
   action = [ '$SCRIPT_VERSION_UPD $BS_DIR_SRCROOT /kb/foo ' + verCfg.srcnode().path,  ## Why srcnode()?
              ## Why do this? 
              Copy(verCfg.path, verCfg.srcnode().path) ]
 )

 env.Command(
   target = verHH,
   source = [ verCfg, scriptVerGen ],  
   ## How about this change
   action = '$SCRIPT_VERSION_GEN $TARGET' + verCfg.path
 )