从不同项目的SConstru重用环境

2024-07-02 13:46:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我得到了一个完整的源代码存档(称之为legacyProject),它有一个SConstruct构建脚本。这个构建脚本做了大量的工作来创建一个好的定制的Environment,它理解一个微控制器的定制工具链。它还有几个helper函数,可以简化相当大的构建矩阵的Program语句的生成。你知道吗

我正在启动一个相关的项目,可以几乎一字不差地重用这个Environment和相关代码。我不想把所有东西都复制粘贴到一个新的SConstruct文件中,因为原始文件可能会收到补丁(更不用说这只是代码的重复)。目前,这些项目在文件系统中并排进行:

myProject/
    SConstruct
legacyProject/
    SConstruct

我可能会重新排列它们,以便legacyProjectmyProject的子目录,这样我就可以使用版本控制跟踪精确的修订。你知道吗

myProject/
    SConstruct
    legacyProject/
        SConstruct

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

SConscript('legacyProject/SConstruct')

只返回“无”。你知道吗


Tags: 文件工具项目函数代码helper脚本environment
2条回答

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

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

如果不将遗留的SConstruct中的一些功能重构到一个helper文件中,我认为没有办法做到这一点。你知道吗

如果可以重构代码,那么有三种可能的替代方法可用——一种是使用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
  • 您不希望将额外的标志传递给scon或设置环境变量
  • 您试图不知道您使用的是哪种Python安装
  • 你没有使用变体目录

通过Python模块重用

如果要将scons实用程序打包为python包,可以采用两种方法。你知道吗

首先是使用传统的Python打包技术。有一些很好的指南-我推荐Python Packaging User Guide。要使其正常工作,您需要编写一个setup.py,并使用pippython setup.py install安装

使这个问题变得棘手的是,可以同时安装多个Python和scon,它们通过PATH环境变量微妙地耦合在一起。这可能意味着在一台机器上工作的东西可能在另一台机器上不工作。你知道吗

一种更常见的方法是修改python用于在sconstruct中搜索模块的路径——从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重用

如果希望在不更改多个scon结构的情况下动态地向多个scon结构添加功能,可以使用scon支持的内置扩展性(请参阅用户手册Where To Put Your Custom Builders and Tools中的部分或在SCons Man Page中搜索 site-dir=dir

在这种情况下,您可以:

.
├── 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'

结构是:

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

但是您需要使用以下命令调用scon(从myProject/legacyProject目录):

scons  site-dir=../common

如果:

  • 您希望对两个项目生成都进行更改,而不更改其中一个的代码。你知道吗

相关问题 更多 >