5

我最近选择了 scons 来为一个中型 C++ 项目实现一个多平台构建框架。构建会生成一堆单元测试,这些单元测试应该在它结束时被调用。一个人是如何做到这一点的?

例如在我的顶级结构中,我有

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新手。:)

谢谢,

4

4 回答 4

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 将始终相同,并且它可能决定不执行后续构建步骤。如果您需要对基本命令进行不同的调整,可以使用函数工厂来修改模板。例如

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 构建流程中的内容(例如,在其他所有内容运行后压缩所有构建日志文件的内容),请在此处查看我的问题

于 2009-12-10T19:29:27.153 回答
3

解决方案应该像这样简单。

使测试构建器的结果依赖于安装构建器的结果

在伪:

test = Test(dlls)
result = Install(dlls)
Depends(test,result)

最好的方法是测试构建器实际上为您计算出 dll 依赖项,但可能有各种原因它不这样做。

于 2010-01-11T10:10:39.507 回答
0

只需让每个SConscript返回一个值,您将在该值上构建依赖项。

SConscript 文件:

test = debug_environment.Program('myTest', src_files)
Return('test')

S构造文件:

dep1 = SConscript([...])
dep2 = SConscript([...])
Depends(dep1, dep2)

现在dep1构建将在dep2构建完成后完成。

于 2012-05-24T15:58:17.433 回答
0

在依赖方面,您想要的是所有测试操作都依赖于所有程序构建的操作。这样做的一种方法是创建一个虚拟目标并将其导出到所有子目录的 sconscript 文件中,并在 sconscript 文件中,Depends在主要目标上创建虚拟目标,并在虚拟目标上设置测试Depends目标。

我在弄清楚如何设置虚拟目标时遇到了一些麻烦,但这基本上是可行的:

(在顶级 SConstruct 中)

dummy = env.Command('.all_built', 'SConstruct', 'echo Targets built. > $TARGET')
Export('dummy')

(在每个子目录的 SConscript 中)

Import('dummy')
for target in target_list:
  Depends(dummy, targe)
for test in test_list:
  Depends(test, dummy)

我敢肯定,进一步的改进是可能的,但也许这会让你开始。

编辑:也值得指出这个主题的这个页面

于 2009-12-10T18:22:15.063 回答