Scons 循环依赖
Scons Cyclic Dependency
我们从 scons 2.4.1 更新到 2.5.1,突然出现如下几个错误:
scons:*** 找到依赖周期:
内部错误:找不到节点的循环...
我认为这个问题与版本文件有关,如果我们的 SCM 检测到对源文件的编辑,我们会尝试自动更新该版本文件。该过程的要点是我们维护一个包含#defines 的文件'version.cfg'。此文件已签入我们的 SCM。如果该文件已经更新过一次,则在该文件提交给 SCM 之前不会进行第二次更新。然后使用此文件自动生成名为 'kb_version.hh'.
的 C++ 头文件
什么是循环依赖,如何消除它? (请注意,无论是什么问题,都不会导致 scons 2.4.1 出现问题(只有我们使用新版本 2.5.1 才能检测到循环依赖)。
相关的 scons 片段如下:
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
)
一些内联问题。在上面的评论部分不容易做到..
(见下面的 ## 评论)
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
)
我能够找到问题所在,但我不确定这是否是 scons 所希望的行为。
问题是这样的。
(1) C++源文件依赖version.h(通过#include方式)
(2) version.h 是从 version.cfg 自动生成的
(3) 如果任何源文件已更新,version.cfg 将自动递增,其中包括依赖于 version.h 的源文件(因此是循环依赖)。但是,c++ 源文件可能不会发生实际更改,但文件本身 #includes version.h。所以我们的意图是,当且仅当源文件本身发生变化时,才应该更新 version.cfg(而不是编译源文件产生的目标文件)。
在下面的评论中,可以通过从第一个 env.Command() 调用的 "source = " 行中删除 SOURCE 变量来消除循环依赖。
在 scons 中有没有办法说我依赖于源文件,而不是目标文件?或者这是循环依赖中的bug/nuance?
我们从 scons 2.4.1 更新到 2.5.1,突然出现如下几个错误: scons:*** 找到依赖周期: 内部错误:找不到节点的循环...
我认为这个问题与版本文件有关,如果我们的 SCM 检测到对源文件的编辑,我们会尝试自动更新该版本文件。该过程的要点是我们维护一个包含#defines 的文件'version.cfg'。此文件已签入我们的 SCM。如果该文件已经更新过一次,则在该文件提交给 SCM 之前不会进行第二次更新。然后使用此文件自动生成名为 'kb_version.hh'.
的 C++ 头文件什么是循环依赖,如何消除它? (请注意,无论是什么问题,都不会导致 scons 2.4.1 出现问题(只有我们使用新版本 2.5.1 才能检测到循环依赖)。
相关的 scons 片段如下:
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
)
一些内联问题。在上面的评论部分不容易做到.. (见下面的 ## 评论)
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
)
我能够找到问题所在,但我不确定这是否是 scons 所希望的行为。
问题是这样的。 (1) C++源文件依赖version.h(通过#include方式) (2) version.h 是从 version.cfg 自动生成的 (3) 如果任何源文件已更新,version.cfg 将自动递增,其中包括依赖于 version.h 的源文件(因此是循环依赖)。但是,c++ 源文件可能不会发生实际更改,但文件本身 #includes version.h。所以我们的意图是,当且仅当源文件本身发生变化时,才应该更新 version.cfg(而不是编译源文件产生的目标文件)。
在下面的评论中,可以通过从第一个 env.Command() 调用的 "source = " 行中删除 SOURCE 变量来消除循环依赖。
在 scons 中有没有办法说我依赖于源文件,而不是目标文件?或者这是循环依赖中的bug/nuance?