为什么SCons的VariantDir()不将输出放在指定目录中?

10 投票
3 回答
10213 浏览
提问于 2025-04-15 12:38

我在考虑用SCons来做一个新项目。这个工具看起来不错,不过我对VariantDir有点搞不懂。

我的项目很简单,只有几个C语言源文件在一个文件夹里。我想要在“正常”和“配置”模式下构建,也就是用两套不同的gcc选项。我希望输出的文件分别放在normal/和profile/这两个文件夹里。

为了测试,我把项目简化成只有一个源文件t.c,里面有一个main()函数。我的文件也在同一个文件夹里,内容如下:

normal = DefaultEnvironment(tools=['mingw'], CCFLAGS = '-O2')
normal.VariantDir('release', '.', duplicate=0)
normal.Program('t', ['t.c'])

#profile = normal.Clone(CCFLAGS='-O2 -pg', LINKFLAGS = '-pg')
#profile.VariantDir('profile', '.', duplicate=0)
#profile.Program('t', ['t.c'])

当我运行scons的时候,我希望它把t.o和t.exe放到release/文件夹里,但它却把它们放在了当前目录。而且如果我把3行配置的代码取消注释,我根本无法运行,出现这个错误:

scons: *** 为同一个目标t.o指定了两个不同操作的环境。

总之,我不明白为什么我的VariantDir()调用没有告诉scons把输出放到指定的输出目录release里。

(我看了不少文档和讨论组的内容,但没有找到能解答这个问题的。最接近的一个是这个页面,它描述了类似的情况,但涉及到一个单独的src/文件夹和两个不同的scons文件,还要在它们之间导入/导出变量。这看起来不太方便。)

3 个回答

5

正如这个链接所说,

请注意,当你没有在src子目录中使用SConscript文件时,你必须明确告诉程序,它需要从build/hello.c文件构建,而这个文件会在build子目录中被SCons复制。

VariantDir('release','.',duplicate=0)
env=Environment()
env.Program('release/t',['release/t.c'])

当我在Linux上运行这个命令时。

scons -u . 
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: building associated VariantDir targets: release
gcc -o release/t.o -c t.c
gcc -o release/t release/t.o
scons: done building targets.

我想在Win32上也能正常工作。

8

我可以通过这个方法把构建目录里的二进制文件分开:

# SConstruct
SConscript('SConscript', variant_dir='build', src_dir='..', duplicate=0)

如果你想把二进制文件放到比当前目录低两个层级的地方,可以这样做:

# SConstruct
SConscript('SConscript', variant_dir='build/release', src_dir='../..', duplicate=0)

简单来说,你需要把src_dir这个参数设置为从你的构建目录回到源代码目录的路径。

9

没错,VariantDir在scons中确实让人困惑。虽然这个信息没有被广泛宣传,但你可以把SConstruct和SConscript放在同一个文件夹里,这样就可以用当前文件夹作为源文件夹。

# SConstruct
SConscript('SConscript', build_dir='build', src='.')

而且

# SConscript
Program('main.c')

我从来没找到过不使用两个文件的方法,同时还能保持理智去理解variant dir :)

撰写回答