使用SCons实现真正的分层构建?

11

我在stackoverflow上阅读了有关分层构建的问题,例如:使用SCons创建分层构建

我想要对两个独立的仓库进行真正的分层构建,它们都使用我使用Mercurial设置为子仓库的scons。下面是文件布局,说明了我想要做的事情。

期望的布局:

project_root/  (new project that builds bar app using the libfoo built from source)

    libfoo_subrepo/  (standalone project repo from bitbucket)
        src/
            SConscript
            libfoo.c
            libfoo.h
        test/
            SConscript
            test_foo.c
        SConstruct

    barapp_subrepo/  (standalone project repo from bitbucket that uses libfoo)
        src/
            SConscript
            bar.c
            bar.h
        test/
            SConscript
            test_bar.c
        SConstruct

    test/
        SConscript
        test_bar_with_foo.c
    SConstruct
所以我有两个独立的仓库,都使用scons。第一个是libfoo,可以单独克隆并使用scons构建。在libfoo根目录中运行scons时,它会在src/中构建libfoo的静态库,并在test/中构建链接到src/中静态库的单元测试可执行文件。

第二个仓库有一个名为bar的应用程序依赖于libfoo。如果在构建系统上安装了libfoo,则可以单独克隆该仓库并使用scons进行构建。
我的想法是设置一个新的仓库(project_root),其中将libfoo和bar应用程序仓库作为子仓库使用mercurial设置。因此,当您克隆此新仓库时,它会自动下载bar应用程序及其依赖项libfoo。然后,我希望能够在这个新仓库的根目录中运行scons,并让它执行libfoo_subrepo / root中的scons来构建libfoo及其单元测试。然后,我希望它在barapp_subrepo / root中运行scons来构建bar并告诉它链接到libfoo_subrepo / src /中的libfoo静态库。最后,我希望它构建一些新的单元测试,在tests /中使用libfoo静态库和bar应用程序的源文件来测试组合在一起的bar应用程序和libfoo。

据我所知,从阅读scons文档可以看出,我需要创建一个“subrepo”的自定义构建器,在子shell中运行scons。然后,我可以将libfoo.subrepo和barapp.subrepo添加到project_root /目录中,并通过某种方式使构建器在执行构建libfoo.subrepo的命令时将源名称转换为路径以在其中执行scons。
building 'libfoo.subrepo' translates into executing 'cd libfoo_subrepo; scons'

我觉得scons不能递归地构建独立的scons项目。所有我读到的都假定你能在子文件夹中创建SConscript文件,然后根SConstruct文件依赖于SConscript文件。请告诉我有没有一种方法可以使用scons实现我想要的功能。我不想回到make。

谢谢。

2个回答

9
我不确定为什么您需要制作自定义构建器,如果我理解正确,我认为您需要的一切都可以通过SCons及其内置构建器完成。
为了实现您所说的内容,您确实需要三个单独的SConsctruct文件来执行三个单独的构建。我还会添加3个SConscript文件,并使它们全部如下所示: 编辑:在这个例子中,在SConstruct脚本中创建Environment()更好
项目根目录/SConstruct
# This SConstruct orchestrates building 3 subdirs

import os

subdirs = ['libfoo_subrepo', 'barapp_subrepo', 'test']
env = Environment()

for subdir in subdirs:
    SConscript(os.path.join(subdir, 'SConscript'), exports = ['env'])

libfoo_subrepo/SConstruct

# This SConstruct does nothing more than load the SConscript in this dir
# The Environment() is created in the SConstruct script
# This dir can be built standalone by executing scons here, or together
# by executing scons in the parent directory
env = Environment()
SConscript('SConscript', exports = ['env'])

libfoo_subrepo/SConscript

# This SConstruct orchestrates building 2 subdirs
import os

Import('env')
subdirs = ['src', 'test']

for subdir in subdirs:
    SConscript(os.path.join(subdir, 'SConscript'), exports = ['env'])

barapp_subrepo/SConstruct

# This SConstruct does nothing more than load the SConscript in this dir
# The Environment() is created in the SConstruct script
# This dir can be build standalone by executing scons here, or together
# by executing scons in the parent directory
env = Environment()
SConscript('SConscript', exports = ['env'])

barapp_subrepo/SConscript

# This SConstruct orchestrates building 2 subdirs
import os

Import('env')
subdirs = ['src', 'test']

for subdir in subdirs:
    SConscript(os.path.join(subdir, 'SConscript'), exports = ['env'])

我希望每个文件中的注释都能解释其目的。
希望这有所帮助。

如果您在此解决方案中使用子目录进行构建,然后从顶层重新构建,那么它不会再次重建整个子目录吗? - Geoffrey Irving
@GeoffreyIrving,说得好。根据项目的规模,这可能并不重要。但是可以通过为根构建和子目录构建指定scons db文件,或者使用不同的变体目录来避免您提到的问题。 - Brady
如果有人现在找到了这个,你可以使用SConscript(dirs=subdirs, exports=["env"])来代替手动循环。 - joki

-4
SConscript(dirs=['src', 'doc'])

这并没有提供问题的答案。如果要批评或请求作者澄清,请在他们的帖子下留言 - 您始终可以在自己的帖子上发表评论,并且一旦您拥有足够的声望,您将能够评论任何帖子 - Carl0s1z
@CTravel 为什么你认为这是澄清或批评,而不是(至少是尝试)回答呢? - Mathias Müller
@MathiasMüller 这更像是一条评论而不是答案,他需要解释他的答案,而不仅仅是发布一些代码。 - Carl0s1z
1
@CTravel 我看到很多答案只包含代码,但在我看来是有效的。这不是评论,而是一个答案 - 尽管不是非常有用,但这就是为什么有踩的存在。 - Mathias Müller
+1,我同意你的观点。感谢你向我提出。 - Carl0s1z

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接