从不同项目的SConstruct重用环境

时间:2015-08-29 05:47:43

标签: python scons

我收到了一个已完成的源存档(称为legacyProject),其中包含SConstruct构建脚本。这个构建脚本做了很多工作来创建一个很好的自定义Environment,它可以理解微控制器的自定义工具链。它还有一些辅助函数,可以简化为相当大的构建矩阵生成Program语句。

我正在开始一个相关的项目,几乎可以逐字地重用这个Environment及相关代码。我不想只是将所有内容复制粘贴到新的SConstruct文件中,因为原始版本可能会收到补丁(更不用说它只是重复代码)。目前,这些项目在文件系统中是并排的:

myProject/
    SConstruct
legacyProject/
    SConstruct

我可能会重新安排它们,以便legacyProjectmyProject的子目录,因此我可以通过版本控制跟踪确切的修订。

myProject/
    SConstruct
    legacyProject/
        SConstruct

有没有办法从legacyProject/SConstruct导入所有代码?使用Python模块,这对于import来说是微不足道的,但我不知道这是否可行与Scons。我的尝试:

SConscript('legacyProject/SConstruct')

只返回无。

2 个答案:

答案 0 :(得分:2)

如果不将旧版SConstruct中的某些功能重构为帮助文件,我不相信有办法做到这一点。

如果你可以重构代码,那么有三种可能的替代方法可用 - 一种是使用SCons内置的现有SConscript机制,另一种是使用python模块,最后一种方法是使用site-dir选项。

通过SConscripts重复使用

假设项目结构如下:

.
├── common
│   └── SConscript
├── legacyProject
│   └── SConstruct
└── myProject
    └── SConstruct

您的SConstruct文件将创建一个环境,然后执行common/SConscript,它返回一个修改过的环境。例如,如果您想在公共目录中收集一些选项,最终可能会出现以下内容:

# common/SConscript
Import('env')
env['CCFLAGS']  = '-Wall -Wextra -pedantic'
Return('env')

# myProject/SConstruct (similar for legacy/SConstruct)
env = Environment()
print 'before:', env['CCFLAGS']
env = SConscript('../common/SConscript', exports = 'env')
print 'after:', env['CCFLAGS']

选择此方法:

  • 你熟悉SCons,但不太熟悉Python
  • 您不希望将额外标志传递给scons或设置环境变量
  • 您正试图不知道您正在使用哪种Python安装
  • 您没有使用变体目录

通过Python模块重用

如果您要将scons实用程序打包为python包,则可以使用两条路径。

首先是使用传统的Python封装技术。有一些很好的指南 - 我推荐Python Packaging User Guide。为了实现这一目标,您需要编写setup.py,并使用pippython setup.py install进行安装

使这个棘手的是你可以有多个并行安装的Python和SCons,它们通过你的PATH环境变量巧妙地耦合。这可能意味着在一台机器上工作的东西可能无法在另一台机器上运行。

一种更常见的方法是修改python用于在SConstructs中搜索模块的路径 - 从Python角度来看糟糕的做法,但稍微更易于维护,特别是如果您的构建机器很复杂。

假设项目结构如下:

.
├── common
│   └── __init__.py
├── legacyProject
│   └── SConstruct
└── myProject
    └── SConscript

你的python模块可以非常简单:

# common/__init__.py
def set_warning_flags(env):
    env['CCFLAGS']  = '-Wall -Wextra -pedantic'

# myProject/SConstruct
import sys
sys.path.insert(0, '..')
import common

env = Environment()
print 'before:', env['CCFLAGS']
common.set_warning_flags(env)
print 'after:', env['CCFLAGS']

选择此方法:

  • 您有很多外部配置(许多构建器/复杂环境),只需从几个地方拉入。
  • 您没有使用变体构建

通过site-dir / site-init重用

如果要动态添加功能到多个SConstructs而不更改它们,可以使用SCons支持的内置可扩展性(请参阅用户手册Where To Put Your Custom Builders and Tools中的部分或搜索--site-dir=dirSCons Man Page

在这种情况下,您将拥有:

.
├── common
│   └── site_init.py
├── legacyProject
│   └── SConstruct
└── myProject
    └── SConstruct

site_init.py的位置:

# common/site_init.py
def set_warning_flags(env):
    env['CCFLAGS']  = '-Wall -Wextra -pedantic'

SConstruct是:

env = Environment()
print 'before:', env['CCFLAGS']
set_warning_flags(env)
print 'after:', env['CCFLAGS']

但您需要使用以下命令调用SCons(来自myProject / legacyProject目录)

scons --site-dir=../common

选择此方法:

  • 您希望在不更改任何代码的情况下对两个项目构建进行更改。

答案 1 :(得分:0)

我建议将要共享的逻辑重新设计到导入的python模块中,并在SConstruct中调用一些初始化。这将是最干净的方法(恕我直言)。

虽然你可以使用pythons execfile()(我相信),但这是一个混乱的方法。