我有一个别名,可以构建一些名为'build_packages'
的包。但是,除非在它之前构建特定的代码转换器库,否则不会构建此别名:'transcoderLib'
。 'transcoderLib'
也是一个别名,并且自身构建得很好。我尝试指定我的别名依赖项,如下所示:
env.Alias('transcoderLib')
...
Default(env.Alias('build_packages'))
Depends('build_packages', 'transcoderLib')
如果我构建'build_packages'
,则根本不构建'transcoderLib'
,并且构建失败,因为'build_packages'
依赖于它。为什么scons没有接受依赖?
更多信息:在我声明这两个别名时,它们都没有任何目标,它们只是空的别名,稍后由SConscripts填充。我希望Depends('build_packages', 'transcoderLib')
在'build_packages'
上定义来自'transcoderLib'
的依赖关系,以便首先构建'transcoderLib'
,然后构建'build_packages'
。
编辑:为了增加这种混乱,我发现当我使用scons --tree=derived,prune
时,它会打印出'build_packages'
的所有正确依赖项!如果它看到依赖关系,为什么不建立它们?!!!这是构建树本身(当然是修剪,NDAs等):
+-build_packages
+-Build\Config\Package_1
| +-Package_1_Dependencies...
+-Build\Config\Package_2
| +-Package_2_Dependencies...
...etc... for 16+ packages...
+-transcoderLib
+-Build\Transcoder.dll
| +-DLL dependencies...
+-Build\Transcoder.lib
| +-LIB dependencies
+-Build\Transcoder.exp
| +-EXP depdendencies
+-Lib\Python\Transcoder.pyd
+-[Build\Transcoder.dll]
+-[Build\Transcoder.lib]
+-[Build\Transcoder.exp]
编辑3:为了提供一个更完整的例子,我安排了一个简单的SConstruct来模仿我相当好的情况(我在编辑2中删除了前面的例子以避免混淆)。真正的问题是Python文件正在导入'transcoderLib'目标,因此scons甚至不知道在构建包之前需要构建库。我试图告诉scons这是必要的。这是一个简单的例子:
import SCons
import shutil
import os
env = Environment(tools=['default', 'textfile'])
def package_builder(target, source, env):
cmdLine = 'python test.py'
return os.system(cmdLine)
def copy(env, target, source):
shutil.copy(source[0].path, target[0].path)
env.Append(BUILDERS = { 'copybuilder' : Builder(action = Action(copy, ' COPY $SOURCE -> $TARGET')) } )
env.Append(BUILDERS = { 'package' : Builder(action = Action(package_builder, ' PACKAGE $SOURCES -> $TARGET'), suffix='.zip' ) } )
env.Textfile(target='foo.txt', source='hello, world\n')
config = int(ARGUMENTS.get('config', 0))
if config == 1:
Default(env.Alias('build_packages'))
Depends(env.Alias('build_packages'), env.Alias('transcoderLib'))
env.Alias('transcoderLib', 'foo.txt')
copyTarget = env.copybuilder('bar.txt', 'foo.txt')
env.Alias('transcoderLib', copyTarget)
package = env.package('#Test', [])
env.Alias('build_packages', package)
当然还有test.py,这是一个非常简单的脚本,依赖于bar.txt,'transcoderLib'的目标:
import os
if not os.path.exists('bar.txt'):
raise Exception("bar.txt wasn't created yet!")
和输出:
scons: warning: Support for pre-2.7.0 Python version (2.6.2) is deprecated.
If this will cause hardship, contact dev@scons.tigris.org.
File "C:\Python26\Scripts\scons.py", line 192, in
scons: Building targets ...
PACKAGE -> Test.zip
Traceback (most recent call last):
File "test.py", line 3, in
raise Exception("bar.txt wasn't created yet!")
Exception: bar.txt wasn't created yet!
scons: *** [Test.zip] Error 1
当然,如果我首先使用transcoderLib',那么构建'bar.txt'就好了,我可以毫无错误地运行'scons config = 1'。对于那些想知道我为什么使用没有任何源或目标的构建器的人来说,这是为了让我的例子尽可能简单。 'package'构建器应该只运行'test.py'(实际上,它还构建了包,但包的依赖关系与'transcoderLib'完全隔离)。
答案 0 :(得分:3)
如果我正确理解了您要实现的目标,那么您设置了错误的依赖项。我尝试从上面的EDIT 3修改您的SConstruct,如下所示:
import SCons
import shutil
import os
env = Environment(tools=['default', 'textfile'])
def package_builder(target, source, env):
cmdLine = 'python test.py'
return os.system(cmdLine)
def copy(env, target, source):
shutil.copy(source[0].path, target[0].path)
env.Append(BUILDERS = { 'copybuilder' : Builder(action = Action(copy, ' COPY $SOURCE -> $TARGET')) } )
env.Append(BUILDERS = { 'package' : Builder(action = Action(package_builder, ' PACKAGE $SOURCES -> $TARGET'), suffix='.zip' ) } )
env.Textfile(target='foo.txt', source='hello, world\n')
#
# Here the changes start
#
# The following line is not needed, SCons picks up the
# dependency bar.txt -> foo.txt automatically
#tclib = env.Alias('transcoderLib', 'foo.txt')
copyTarget = env.copybuilder('bar.txt', 'foo.txt')
# Defining Alias for later reference...
# important: don't create new Alias()es all over
# the place, but pass a single reference around
tclib = env.Alias('transcoderLib', copyTarget)
# Main change: Your initial dependencies were wrong, it's
# the package (='python test.py') that depends on your
# transcoderLib (='bar.txt')...
package = env.package('#Test', [])
env.Depends(package, tclib)
# Create an Alias for the packages, you can pass
# a list of all your packages too here...
bp = env.Alias('build_packages', package)
# Finally, set the package Alias() as default target if
# requested by the config parameter...
config = int(ARGUMENTS.get('config', 0))
if config == 1:
env.Default(bp)
在尝试运行'package'步骤之前,它首先正确构建'bar.txt'。请注意,在更新时,“包”构建器会一次又一次地被调用,因为指定的目标“#Test”永远不会被创建...所以它总是被认为是过时的。
我希望这可以帮助您进一步,或者至少为您提供一些新的想法,如果这不是您一直在寻找的解决方案。
最后评论:只需将所需的依赖项集合添加到所有软件包中,方法是将其添加到包含软件包的Alias中,这将无效。你的Alias被认为是一个不同的目标,所以如果你调用“scons package_1”来构建一个包...依赖项将不会启动。你必须明确并将依赖项添加到每个包中,因为这就是你的构建结构看起来像。
答案 1 :(得分:1)
显然env.Alias()
设置依赖关系,而不是等效关系。所以当你说build_packages依赖于transcoderLib时,你不说bar.txt也依赖于transcoderLib。
考虑您的简单示例生成的树:
$ scons -n -Q --tree=all -f ex.sc config=1
scons: `build_packages' is up to date.
+-build_packages
+-bar.txt
| +-hello, world
+-transcoderLib
+-foo.txt
+-hello, world
正如您所看到的,由于build_packages
电话,bar.txt
取决于env.Alias()
。由于build_packages
来电,transcoderLib
也取决于Depends()
。但bar.txt
和transcoderLib
之间没有任何关系。
如果bar.txt
依赖于transcoderLib
,则需要表达该关系:
Depends('bar.txt', env.Alias('transcoderLib'))
如果该行已添加到您的示例中,则生成的树为:
$ scons -Q --tree=all -f ex1.sc config=1
scons: `build_packages' is up to date.
+-build_packages
+-bar.txt
| +-hello, world
| +-transcoderLib
| +-foo.txt
| +-hello, world
+-transcoderLib
+-foo.txt
+-hello, world