将SCons设置为自动链接

时间:2011-01-25 19:11:52

标签: c++ python scons lint

我正在使用谷歌的cpplint.py来验证我的项目中的源代码是否符合Google C++ Style Guide中规定的标准。我们使用SCons进行构建,所以我想通过让SCons首先读取所有.h和.cc文件然后在它们上运行cpplint.py来自动化该过程,只有在它通过时才构建文件。问题如下:

  1. 在SCons中如何预先挂钩构建过程?在通过linting之前,不应编译任何文件。
  2. cpplint不会返回退出代码。如何在SCons中运行命令并检查结果是否与正则表达式匹配? I.E.,如何输出文本?
  3. 项目很大,无论#1和#2的解决方案如何,当-j选项传递给SCons时,它应该同时运行。
  4. 我需要一个允许某些文件跳过lint检查的白名单。

3 个答案:

答案 0 :(得分:2)

AddPreAction似乎正是您正在寻找的内容,请参阅联机帮助页:

AddPreAction(target, action)
env.AddPreAction(target, action)
Arranges for the specified action to be performed before the specified target is built. T

另见http://benno.id.au/blog/2006/08/27/filtergensplint示例。

答案 1 :(得分:2)

实现此目的的一种方法是monkey patch对象发射器功能,它将C ++代码转换为可链接的目标文件。有2个这样的发射器功能;一个用于静态对象,一个用于共享对象。下面是一个示例,您可以将粘贴复制到SConstruct中:

import sys
import SCons.Defaults
import SCons.Builder
OriginalShared = SCons.Defaults.SharedObjectEmitter
OriginalStatic = SCons.Defaults.StaticObjectEmitter

def DoLint(env, source):
    for s in source:
        env.Lint(s.srcnode().path + ".lint", s)

def SharedObjectEmitter(target, source, env):
    DoLint(env, source)
    return OriginalShared(target, source, env)

def StaticObjectEmitter(target, source, env):
    DoLint(env, source)
    return OriginalStatic(target, source, env)

SCons.Defaults.SharedObjectEmitter = SharedObjectEmitter
SCons.Defaults.StaticObjectEmitter = StaticObjectEmitter
linter = SCons.Builder.Builder(
    action=['$PYTHON $LINT $LINT_OPTIONS $SOURCE','date > $TARGET'],
    suffix='.lint',
    src_suffix='.cpp')

# actual build
env = Environment()
env.Append(BUILDERS={'Lint': linter})
env["PYTHON"] = sys.executable
env["LINT"] = "cpplint.py"
env["LINT_OPTIONS"] = ["--filter=-whitespace,+whitespace/tab", "--verbose=3"]
env.Program("test", Glob("*.cpp"))

真的没有什么太棘手的。您将LINT设置为cpplint.py副本的路径,并为项目设置适当的LINT_OPTIONS。如果检查通过命令行date程序传递,则唯一的问题是创建TARGET文件。如果你想成为跨平台,那就必须改变。

添加白名单现在只是常规的Python代码,例如:

whitelist = """"
src/legacy_code.cpp
src/by_the_PHB.cpp
"""".split()

def DoLint(env, source):
    for s in source:
        src = s.srcnode().path
        if src not in whitelist:
            env.Lint( + ".lint", s)

似乎cpplint.py确实输出了正确的错误状态。当有错误时它返回1,否则返回0.所以没有额外的工作要做。如果lint检查失败,它将无法构建。

此解决方案适用于-j,但C ++文件可能会编译,因为lint假输出和目标文件目标之间没有隐式依赖关系。您可以在其中添加显式env.Depends以强制“.lint”输出依赖于对象目标。因为它可能已经足够了,因为即使在所有C ++编译之后,如果有任何剩余的lint问题,构建本身也将失败(scons给出非零返回码)。为了完整性,在DoLint函数中依赖代码将是这样的:

def DoLint(env, source, target):
    for i in range(len(source)):
        s = source[i]
        out = env.Lint(s.srcnode().path + ".lint", s)
        env.Depends(target[i], out)

答案 2 :(得分:1)

请参阅我的github以获取一对带有示例源树的scons脚本。它使用Google的cpplint.py。

https://github.com/xyzisinus/scons-tidbits