我正在使用scons来编译我的项目。 在我的项目中,源文件位于不同的目录中。 我们是否需要在每个目录中使用sconscript文件来编译这些项目源文件?
我尝试使用单个sconscript文件编译所有目录。但是所有目标文件都只添加到我的源目录中。
我正在使用此功能:
env.Library('libs',files_list)
如果files_list包含唯一的文件名,则Obj文件正在生成@ variant目录。
如果files_list包含文件路径名,则Obj文件正在生成@ source目录。
你能告诉我怎么做吗?
答案 0 :(得分:14)
我准备了一个示例,演示了如何使用SCons VariantDir()函数只使用一个SConstruct脚本(没有辅助SConscripts)来编译像您这样的项目。我决定在单独的答案中这样做,以便更容易阅读。
VariantDir()函数没有很好地记录,所以你提到的关于编译目标文件的位置的行为不是直接修复的。 “技巧”是指变体目录中的所有源文件,而不是实际的源目录,如下所示。
以下是我项目中源文件的结构:
$ tree .
.
├── SConstruct
├── src1
│ ├── class1.cc
│ └── class1.h
├── src2
│ ├── class2.cc
│ └── class2.h
└── srcMain
└── main.cc
这是SConstruct:
env = Environment()
# Set the include paths
env.Append(CPPPATH = ['src1', 'src2'])
# Notice the source files are referred to in the build dir
# If you dont do this, the compiled objects will be in the src dirs
src1Sources = ['build/lib1/class1.cc']
src2Sources = ['build/lib2/class2.cc']
mainSources = ['build/mainApp/main.cc']
env.VariantDir(variant_dir = 'build/lib1', src_dir = 'src1', duplicate = 0)
env.VariantDir(variant_dir = 'build/lib2', src_dir = 'src2', duplicate = 0)
env.VariantDir(variant_dir = 'build/mainApp', src_dir = 'srcMain', duplicate = 0)
lib1 = env.Library(target = 'build/lib1/src1', source = src1Sources)
lib2 = env.Library(target = 'build/lib1/src2', source = src2Sources)
env.Program(target = 'build/mainApp/main', source = [mainSources, lib1, lib2])
这是编译输出:
$ scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o build/lib1/class1.o -c -Isrc1 -Isrc2 src1/class1.cc
ar rc build/lib1/libsrc1.a build/lib1/class1.o
ranlib build/lib1/libsrc1.a
g++ -o build/lib2/class2.o -c -Isrc1 -Isrc2 src2/class2.cc
ar rc build/lib1/libsrc2.a build/lib2/class2.o
ranlib build/lib1/libsrc2.a
g++ -o build/mainApp/main.o -c -Isrc1 -Isrc2 srcMain/main.cc
g++ -o build/mainApp/main build/mainApp/main.o build/lib1/libsrc1.a build/lib1/libsrc2.a
scons: done building targets.
以下是编译后生成的项目结构:
$ tree .
.
├── build
│ ├── lib1
│ │ ├── class1.o
│ │ ├── libsrc1.a
│ │ └── libsrc2.a
│ ├── lib2
│ │ └── class2.o
│ └── mainApp
│ ├── main
│ └── main.o
├── SConstruct
├── src1
│ ├── class1.cc
│ └── class1.h
├── src2
│ ├── class2.cc
│ └── class2.h
└── srcMain
└── main.cc
应该提到的是,更直接的方法是使用SConscript()函数,指定variant_dir,但如果您的要求不允许这样做,则此示例将起作用。 SCons man page有关于VariantDir()函数的更多信息。在那里你还会发现以下内容:
请注意,VariantDir()最自然地使用辅助SConscript文件。
答案 1 :(得分:2)
回答你的第一个问题:不,没有必要在每个src子目录中都有一个SConscript,以便能够编译该目录中的文件。一切都可以从一个单独的SConstruct完成。
话虽如此,它经常被认为更清洁,更有条理,在src子目录中有一个SConscript。通常在这种情况下,根SConstruct将设置整个项目通用的东西,并协调调用src子目录。然后,每个src子目录中的SConstruct将集中于该子目录的细节。我更喜欢这种方法,因为它更模块化。此外,这将允许您使用不同的环境调用相同的src子目录SConstruct来编译相同代码的不同版本,如调试和发布。
所有这一切都可以通过在SConstruct中创建一个环境,然后使用SConscript()函数将其传递给sudirs来完成。这是一个例子:
SConstruct
env = Environment()
env.Append(CPPPATH = '/some/dir/common/to/all')
SConscript('src/subdirA/SConscript',
variant_dir = 'build/subdirA',
duplicate = 0,
exports = 'env')
SConscript('src/subdirB/SConscript',
variant_dir = 'build/subdirB',
duplicate = 0,
exports = 'env')
的src / subdirA / SConscript
Import('env')
# If you need to add specific things to the env, then you should clone it,
# else the changes will be seen in other subdirs: clonedEnv = env.Clone()
# No need to specify the path to the source files if all source files are in
# the same dir as this SConscript.
env.Library(target='subdirA', source='fileA.cc')
的src / subdirB / SConscript
Import('env')
# If you need to add specific things to the env, then you should clone it,
# else the changes will be seen in other subdirs: clonedEnv = env.Clone()
env.Library(target='subdirB', source='fileB.cc')
至于最后一个问题,我真的不明白你在寻找什么,但是使用我上面解释的选项,得到的编译目标将始终放在VariantDir中。