我最近选择了scons来为中型C ++项目实现一个多平台构建框架。构建生成了一堆单元测试,应该在它的最后调用。如何实现这种目标?
例如,在我的顶级sconstruct中,我有
subdirs=['list', 'of', 'my', 'subprojects']
for subdir in subdirs:
SConscript(dirs=subdir, exports='env', name='sconscript',
variant_dir=subdir+os.sep+'build'+os.sep+mode, duplicate=0)
每个子网都有它的单元测试,但是,因为在它们内部构建的dll和可执行文件之间存在依赖关系 - 我想保持测试的运行,直到所有的子目录都已构建和安装(我的意思是,使用env.Install)。
我应该在哪里编写循环来迭代构建的测试并执行它们?我试过把它放在这个循环之后 - 但是因为scons不能让你控制执行的顺序 - 它会在我想要它之前执行。
请帮助一个scons新手。 :)
感谢,
答案 0 :(得分:5)
SCons和Make一样,使用声明性方法来解决构建问题。你不想告诉SCons如何完成它的工作。您希望记录所有依赖项,然后让SCons解决它如何构建所有内容。
如果在其他内容之前执行某些操作,则需要创建并连接依赖项。
如果要创建dmy touch文件,可以创建自定义构建器,如:
import time
def action(target, source, env):
os.system('echo here I am running other build')
dmy_fh = open('dmy_file','w')
dmy_fh.write( 'Dummy dependency file created at %4d.%02d.%02d %02dh%02dm%02ds\n'%time.localtime()[0:6])
dmy_fh.close()
bldr = Builder(action=action)
env.Append( BUILDERS = {'SubBuild' : bldr } )
env.SubBuild(srcs,tgts)
将时间戳放入虚拟文件非常重要,因为scons使用md5哈希值。如果您有一个空文件,则md5将始终相同,并且可能决定不执行后续构建步骤。如果需要在基本命令上生成不同的调整,可以使用函数工厂来修改模板。 e.g。
def gen_a_echo_cmd_func(echo_str):
def cmd_func(target,source,env):
cmd = 'echo %s'%echo_str
print cmd
os.system(cmd)
return cmd_fun
bldr = Builder(action = gen_a_echo_cmd_func('hi'))
env.Append(BUILDERS = {'Hi': bldr})
env.Hi(srcs,tgts)
bldr = Builder(action = gen_a_echo_cmd_func('bye'))
env.Append(BUILDERS = {'Bye': bldr})
env.Bye(srcs,tgts)
如果您想要自动注入scons构建流程(例如,在其他所有内容运行后压缩所有构建日志文件的内容),请参阅my question here。
答案 1 :(得分:2)
解决方案应该像这样简单。
使测试构建器的结果取决于“安装”构建器的结果
在伪:
test = Test(dlls)
result = Install(dlls)
Depends(test,result)
最好的方法是,如果“测试”构建器实际上为您计算了dll依赖项,但可能有各种原因它不会这样做。
答案 2 :(得分:0)
就依赖性而言,您希望所有测试操作依赖于所有程序构建的操作。这样做的一种方法是创建虚拟目标并将其导出到所有子目录的sconscript文件,并在sconscript文件中,在主目标上创建虚拟目标Depends
,并拥有测试目标{{ 1}}在虚拟目标上。
我在弄清楚如何设置虚拟目标时遇到了一些麻烦,但这基本上有效:
(在顶级SConstruct中)
Depends
(在每个子目录的SConscript中)
dummy = env.Command('.all_built', 'SConstruct', 'echo Targets built. > $TARGET')
Export('dummy')
我确信可以进行进一步的改进,但也许这会让你开始。
编辑:也值得指出this page这个主题。
答案 3 :(得分:0)
让每个SConscript
返回一个您将构建依赖关系的值。
SConscript文件:
test = debug_environment.Program('myTest', src_files)
Return('test')
SConstruct文件:
dep1 = SConscript([...])
dep2 = SConscript([...])
Depends(dep1, dep2)
现在dep1
构建将在dep2
构建完成后完成。