Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SCons: Dependency cycles?

Tags:

scons

I'm trying to get SCons to copy a Makefile project from the source dir to the build dir and run some commands to produce libmoo.a, but I'm running into a dependency cycle error. Details follow:

./SConstruct:

env = Environment()
Export('env')

dirs = ['.']

variant_dir = 'build'

for dir in dirs:
        SConscript(dir + '/' + 'SConscript', variant_dir=variant_dir + '/' + dir, duplicate=0)

./SConscript:

import os
Import('env')

env.Command(env.Dir('moo2').abspath, env.Dir('#moo').abspath, ["echo copying moo to the build dir", Copy("$TARGET", "$SOURCE")])

env.Command(env.Dir('moo2/Makefile').abspath, env.Dir('moo2').abspath, 'echo would run moo2.configure')

moolib = env.Command(env.Dir('moo2/libmoo.a').abspath, env.Dir('moo2/Makefile').abspath, 'echo would run make')

Default(moolib)

Error running scons:

scons: *** Found dependency cycle(s):
  build/moo2/Makefile -> build/moo2 -> build/moo2/Makefile
  build/moo2/libmoo.a -> build/moo2 -> build/moo2/Makefile -> build/moo2/libmoo.a

Also tried without using .abspath, but that shouldn't matter, right?

I don't see any cycles:

  • build/moo2/libmoo.a requires build/moo2/Makefile
  • build/moo2/Makefile requires build/moo2
  • build/moo2 requires (source/)moo

How is scons seeing a cycle? It seems to think that build/moo2/Makefile depends on build/moo2/libmoo.a, which is not what I intended to specify.

Any related suggestions are also welcome :-)

like image 537
Pavel Avatar asked Sep 12 '11 16:09

Pavel


1 Answers

There's no need for the env.Dir('moo').abspath anywhere in your SConscript. So that would change it to:

Import('env')
env.Command('moo2', '#moo', ["echo copying moo to the build dir", Copy("$TARGET", "$SOURCE")])
env.Command('moo2/Makefile', 'moo2', 'echo would run moo2.configure')  # Look Here
moolib = env.Command('moo2/libmoo.a', 'moo2/Makefile', 'echo would run make')
Default(moolib)

But that still yields the same error:

scons: *** Found dependency cycle(s):
build/moo2/Makefile -> build/moo2 -> build/moo2/Makefile
build/moo2/libmoo.a -> build/moo2/Makefile -> build/moo2/libmoo.a

So why is that? SCons automatically makes a directory depend on all the files contained within. See the line with the "# Look Here" comment. You've added a dependency moo2/Makefile now depends on moo2. moo2 depends on all it's contents by default, and thus your cycle.

So how do we fix it?

Import('env')
env.Install('moo2',Glob('#moo/*'))
env.Command('moo2/Makefile', env.Glob('moo2/*'), 'echo would run moo2.configure')
moolib = env.Command('moo2/libmoo.a', 'moo2/Makefile', 'echo would run make')
Default(moolib)

I've changed from using Copy() to env.Install(). Since Copy is not attached to the build Environment() object, it won't know about the variant dir. Install() and Copy() are functionally equivalent, with env.Install() being env aware. Additionally I have it copying/depending on all the files in the directory, rather than the directory itself.

Now let's give that a try:

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python /Users/bdbaddog/devel/scons/trunk/bootstrap/src/script/scons.py --tree=prune
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
Install file: "moo/abc.c" as "build/moo2/abc.c"
Install file: "moo/configure" as "build/moo2/configure"
Install file: "moo/def.c" as "build/moo2/def.c"
echo would run moo2.configure
would run moo2.configure
echo would run make
would run make
+-build/moo2/libmoo.a
  +-build/moo2/Makefile
  | +-build/moo2/abc.c
  | | +-moo/abc.c
  | +-build/moo2/configure
  | | +-moo/configure
  | +-build/moo2/def.c
  | | +-moo/def.c
  | +-/bin/echo
  +-/bin/echo
scons: done building targets.

Note the "--tree=prune" this flag will have SCons print out the dependency tree and prune duplications in the tree (so if a 2 files depend on the same tree of files, you'll only see it once)

like image 138
bdbaddog Avatar answered Oct 02 '22 16:10

bdbaddog