You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从SConscript调用的辅助脚本中调用SCons全局函数?

问题描述

我将计算特定源文件和头文件目录路径的复杂逻辑抽离到单独的.py文件中,供多个SConscript导入复用。但现在在这个辅助脚本中调用SCons全局函数Glob时遇到了问题——此前该函数可在SConscript中直接调用,放到独立辅助脚本后却找不到调用方式,我对Python并不熟悉,希望解决这个问题。

更新:关于SCons全局函数的特殊处理

通过查看SCons主入口文件(SConscript.py,与源码树中分散的SConscript文件不同)的代码,发现Glob()能作为全局函数调用是SCons的特殊处理逻辑:

_DefaultEnvironmentProxy = None

def get_DefaultEnvironmentProxy():
    global _DefaultEnvironmentProxy
    if not _DefaultEnvironmentProxy:
        default_env = SCons.Defaults.DefaultEnvironment()
        _DefaultEnvironmentProxy = SCons.Environment.NoSubstitutionProxy(default_env)
    return _DefaultEnvironmentProxy

class DefaultEnvironmentCall(object):
    """A class that implements "global function" calls of
    Environment methods by fetching the specified method from the
    DefaultEnvironment's class.  Note that this uses an intermediate
    proxy class instead of calling the DefaultEnvironment method
    directly so that the proxy can override the subst() method and
    thereby prevent expansion of construction variables (since from
    the user's point of view this was called as a global function,
    with no associated construction environment)."""
    def __init__(self, method_name, subst=0):
        self.method_name = method_name
        if subst:
            self.factory = SCons.Defaults.DefaultEnvironment
        else:
            self.factory = get_DefaultEnvironmentProxy
    def __call__(self, *args, **kw):
        env = self.factory()
        method = getattr(env, self.method_name)
        return method(*args, **kw)


def BuildDefaultGlobals():
    """
    Create a dictionary containing all the default globals for
    SConstruct and SConscript files.
    """

    global GlobalDict
    if GlobalDict is None:
        GlobalDict = {}

        import SCons.Script #     <-------This is referring to a directory with a file named __init__.py, which I've learned is something special in Python
        d = SCons.Script.__dict__
        def not_a_module(m, d=d, mtype=type(SCons.Script)):
             return not isinstance(d[m], mtype)
        for m in filter(not_a_module, dir(SCons.Script)):
             GlobalDict[m] = d[m]

    return GlobalDict.copy()

我尝试在辅助脚本中导入SCons.Script:

import SCons.Script

但仍报错:

NameError: name 'Glob' is not defined:
  File "D:\Git\......\SConstruct", line 412:
    SConscript(theSconscript, duplicate=0)
  File "c:\python37\lib\site-packages\scons\SCons\Script\SConscript.py", line 671:
    return method(*args, **kw)
  File "c:\python37\lib\site-packages\scons\SCons\Script\SConscript.py", line 608:
    return _SConscript(self.fs, *files, **subst_kw)
  .
  .
  .
  File "D:\Git\........\SConscript", line 433:
  .
  .
  .
  File "D:\Git\............\PathSelector.py", line 78:
    src_files.extend(Glob((os.path.join(src_path_a, '*.c')), strings=1))
解决方案

根据SCons的实现逻辑,全局Glob实际是代理到默认环境的方法,在独立Python脚本中需要显式通过模块或环境对象调用,有两种可行方式:

方式一:直接通过SCons.Script模块调用

修改辅助脚本中的代码,给Glob加上模块前缀:

import SCons.Script
# 替换原有的Glob调用
src_files.extend(SCons.Script.Glob(os.path.join(src_path_a, '*.c'), strings=1))

或者也可以直接导入Glob函数:

from SCons.Script import Glob
# 这样就能直接用Glob(...)调用了
src_files.extend(Glob(os.path.join(src_path_a, '*.c'), strings=1))

方式二:获取默认环境后调用其Glob方法

直接获取SCons的默认构建环境,调用环境的Glob方法:

import SCons.Defaults
default_env = SCons.Defaults.DefaultEnvironment()
src_files.extend(default_env.Glob(os.path.join(src_path_a, '*.c'), strings=1))

额外建议

如果你的辅助脚本需要和特定构建环境交互,更推荐从调用它的SConscript中传递环境对象。比如在SConscript中:

# 导入辅助模块
import PathSelector
# 把当前构建环境env传进去
PathSelector.your_function(env, ...)

然后在辅助脚本中使用传入的环境调用Glob:

def your_function(env, ...):
    src_files.extend(env.Glob(os.path.join(src_path_a, '*.c'), strings=1))

这种方式能保证和当前构建环境的配置一致,更灵活可靠。


内容的提问来源于stack exchange,提问作者phonetagger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:30:42