3

我有时想从 SCons 的 Glob 结果中排除某些源文件。通常是因为我想用不同的选项编译那个源文件。像这样的东西:

objs = env.Object(Glob('*.cc'))
objs += env.Object('SpeciallyTreatedFile.cc', CXXFLAGS='-O0')

当然,这给 SCons 带来了问题:

scons: *** Two environments with different actions were specified
       for the same target: SpeciallyTreatedFile.o

我通常使用以下成语解决此问题:

objs = env.Object([f for f in Glob('*.cc')
  if 'SpeciallyTreatedFile.cc' not in f.path])

但这很丑陋,如果要过滤掉多个文件,那就更丑陋了。

有没有更清晰的方法来做到这一点?

4

2 回答 2

7

我厌倦了[f for f in Glob ...]在几个地方重复表达式,所以我编写了以下帮助方法并将其添加到构建环境中:

import os.path

def filtered_glob(env, pattern, omit=[],
  ondisk=True, source=False, strings=False):
    return filter(
      lambda f: os.path.basename(f.path) not in omit,
      env.Glob(pattern))

env.AddMethod(filtered_glob, "FilteredGlob");

现在我可以写了

objs = env.Object(env.FilteredGlob('*.cc',
  ['SpeciallyTreatedFile.cc', 'SomeFileToIgnore.cc']))
objs += env.Object('SpeciallyTreatedFile.cc', CXXFLAGS='-O0')

使用这种模式很容易编写类似的东西,例如,使用正则表达式过滤器作为omit参数,而不是简单的文件名列表,但这很适合我当前的需求。

于 2012-09-20T18:30:57.583 回答
1

这是一个老问题,但值得更新,因为它仍然出现在搜索中。

SCons 2.3.5 为 引入了exclude关键字参数Glob,因此以下内容现在有效:

objs = env.Object(Glob('*.cc'), exclude=['SpeciallyTreatedFile.cc'])
objs += env.Object('SpeciallyTreatedFile.cc', CXXFLAGS='-O0')

由于exclude需要一个列表,因此可以包含许多排除项,并且排除列表本身可能包含与 glob 相同类型的通配符。用户文档列出了以下示例:

sources = Glob('*.cpp', exclude=['os_*_specific_*.cpp']) + Glob('os_%s_specific_*.cpp'%currentOS)
于 2020-12-01T17:47:31.600 回答