scons - 在构建所有目标之后/如何运行某些内容

发布于 2024-08-14 01:24:11 字数 547 浏览 1 评论 0原文

我最近选择了 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 新手。 :)

谢谢,

I've recently picked up scons to implement a multi-platform build framework for a medium sized C++ project. The build generates a bunch of unit-tests which should be invoked at the end of it all. How does one achieve that sort of thing?

For example in my top level sconstruct, I have

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)

Each of the subdir has its unit-tests, however, since there are dependencies between the dlls and executables built inside them - i want to hold the running of tests until all the subdirs have been built and installed (I mean, using env.Install).

Where should I write the loop to iterate through the built tests and execute them? I tried putting it just after this loop - but since scons doesn't let you control the order of execution - it gets executed well before I want it to.

Please help a scons newbie. :)

thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

窗影残 2024-08-21 01:24:11

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

SCons, like Make, uses a declarative method to solving the build problem. You don't want to tell SCons how to do its job. You want to document all the dependencies and then let SCons solve how it builds everything.

If something is being executed before something else, you need to create and hook up the dependencies.

If you want to create dmy touch files, you can create a custom builder like:

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)

It is very important to put the timestamp into the dummy file, because scons uses md5 hashes. If you have an empty file, the md5 will always be the same and it may decide to not do subsequent build steps. If you need to generate different tweaks on a basic command, you can use function factories to modify a template. 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)

If you have something that you want to automatically inject into the scons build flow ( e.g. something that compresses all your build log files after everything else has run ), see my question here.

匿名。 2024-08-21 01:24:11

解决方案应该就是这么简单。

安装构建器的结果

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

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

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

The solution should be as simple as this.

Make the result of the Test builders depend on the result of the Install builder

In pseudo:

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

The best way would be if the Test builder actually worked out the dll dependencies for you, but there may be all kinds of reasons it doesn't do that.

濫情▎り 2024-08-21 01:24:11

就依赖性而言,您希望所有测试操作都依赖于所有程序构建的操作。实现此目的的一种方法是创建一个虚拟目标并将其导出到所有子目录的 sconscript 文件,并在 sconscript 文件中,使虚拟目标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)

我确信可以进一步细化,但也许这会让你开始。

编辑:还值得指出关于该主题的此页面

In terms of dependencies, what you want is for all the test actions to depend on all the program-built actions. A way of doing this is to create and export a dummy-target to all the subdirectories' sconscript files, and in the sconscript files, make the dummy-target Depends on the main targets, and have the test targets Depends on the dummy-target.

I'm having a bit of trouble figuring out how to set up the dummy target, but this basically works:

(in top-level SConstruct)

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

(in each sub-directory's SConscript)

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

I'm sure further refinements are possible, but maybe this'll get you started.

EDIT: also worth pointing out this page on the subject.

仅此而已 2024-08-21 01:24:11

只需让每个 SConscript 返回一个您将构建依赖项的值即可。

SConscript 文件:

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

SConstruct 文件:

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

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

Just have each SConscript return a value on which you will build dependencies.

SConscript file:

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

SConstruct file:

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

Now dep1 build will complete after dep2 build has completed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文