如何解决“scons:警告:为目标指定了两种不同的环境”

时间:2011-06-01 00:04:08

标签: scons

假设我有一个SConstruct文件,如下所示:

env = Environment()

env.Program("a", ["a.c", "util.c"])
env.Program("b", ["b.c", "util.c"])

此版本正常运行,没有SCons警告消息。但是,如果我修改它以为每个Program构建指定不同的库(实际库不相关):

env.Program("a", ["a.c", "util.c"], LIBS="m")
env.Program("b", ["b.c", "util.c"], LIBS="c")

然后我收到警告:

scons: warning: Two different environments were specified for target util.o,
        but they appear to have the same action: $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES

这似乎是由Program构建器自动创建用于构建的新环境引起的,即使它只是LIBS变量不同(并且所以只有 link 步骤需要有不同的环境)。我可以通过以下方式来解决这个问题:

util = env.Object("util.c")
env.Program("a", ["a.c"] + util, LIBS="m")
env.Program("b", ["b.c"] + util, LIBS="c")

这使用单个Object构建器来构建util.c,然后在每个Program构建中使用预编译的目标文件,从而避免警告。但是,这不应该是必要的。有没有更优雅的方法来解决这个问题?或者这实际上是SCons中应该修复的错误吗?

上下文:我将近2000个C源文件编译成大约20个库和120个具有大量共享源的可执行文件。我使用我编写的转换脚本从以前的专有构建系统创建了SConstruct文件。 SCons使用我当前的SConstruct生成了大约450个“两个不同的环境”警告消息,用于完整构建。

4 个答案:

答案 0 :(得分:19)

我找到了一种解决方法,它不涉及创建额外的变量来保存目标文件节点:

env.Program("a", ["a.c", env.Object("util.c")], LIBS="m")
env.Program("b", ["b.c", env.Object("util.c")], LIBS="c")

这会在单个环境中隔离util.c的构建。尽管指定了两次,每次Program一次,SCons不会对此发出警告,因为它是使用相同env对象构建的相同源。当然,在这种情况下,SCons只会编译一次源。

答案 1 :(得分:9)

您可以使用Split函数和自定义帮助程序来简化大型项目的构建过程:

def create_objs(SRCS, path=""):
    return [env.Object(path+src+".cpp") for src in SRCS]

prg1 = Split("file_1 file_2 file_N")
prg2 = Split("file_2 file_5 file_8")

env.Program("a", create_objs(prg1), LIBS="x")
env.Program("b", create_objs(prg2), LIBS="y")

目标文件只创建一次,它们可以在多个构建中使用。希望这会有所帮助...

答案 2 :(得分:1)

我在代码中发现的一个问题是我没有正确使用目标对象路径。或者换句话说,我有一个变量dir指令,但我没有使用BUILDPATH,而是使用了我原来的源代码路径。这样Scons就会找到在目标BUILDPATH和源路径中生成的对象。

答案 3 :(得分:1)

从第一组文件中创建静态库并将库链接到下一组文件(其中包含与第一组文件共有的一些文件)以创建目标。

env.StaticLibrary ("a", ["a.c","util.c"], LIBS = "m")
env.Program ("b", ["b.c","util.c"], LIBS = ["c","a"])