【问题标题】:Do we need sconscript file in every source directory我们是否需要每个源目录中的 sconscript 文件
【发布时间】:2013-03-14 13:50:38
【问题描述】:

我正在使用 scons 来编译我的项目。 在我的项目中,源文件位于不同的目录中。 我们是否需要在每个目录中都有 sconscript 文件来编译那些项目源文件?

我尝试使用单个 sconscript 文件编译所有目录。但是所有目标文件都只添加到我的源目录中。

我正在使用这个功能:

env.Library('libs',files_list)

如果 files_list 包含唯一的文件名,则 Obj 文件正在生成 @variant 目录。

如果 files_list 包含文件路径名,则 Obj 文件正在生成@源目录。

你能告诉我怎么做吗?

【问题讨论】:

  • 能否请您展示一下您的 SConstruct 的其余部分。

标签: python scons


【解决方案1】:

我准备了一个示例,说明如何使用 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 文件一起使用。

【讨论】:

  • 嗨,布雷迪,感谢您的回答,我有一个疑问不在这个话题上。如果我使用 env.program(---) 编译程序,则链接标志为“link /nologo /subsystem:console /pdb:project.pdb /OUT:program.exe D:\build1\subdirA\subdirA. lib D:\build1\subdirB\subdirB.lib main.obj" 它适用于 VC10 编译器。但是对于瑞萨(我的微控制器)编译器,我收到类似“无法打开文件:”\OUT:main.exe“”的错误,它会在链接时接受“-output=start.abs”命令。我怎样才能改变那个。你能告诉我吗
  • @SrinivasReddy,我看到你提出了一个不同的问题,所以我在那里回答了。
【解决方案2】:

回答您的第一个问题:不,不必在每个 src 子目录中都有一个 SConscript 才能编译该目录中的文件。一切都可以通过一个 SConstruct 完成。

话虽如此,通常认为在 src 子目录中有一个 SConscript 会更干净、更有条理。通常在这种情况下,根 SConstruct 会设置整个项目共有的东西,并协调对 src 子目录的调用。然后,每个 src 子目录中的 SConstruct 将专注于该子目录的细节。我更喜欢这种方法,因为它更模块化。此外,这将允许您在不同的环境中调用相同的 src subdir SConstruct 来编译相同代码的不同版本,例如调试和发布。

所有这些都可以通过在 SConstruct 中创建一个环境,然后使用 SConscript() 函数将其传递给 sudirs 来完成。这是一个例子:

S构造

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 中。

【讨论】:

  • 嗨布雷迪谢谢你的回答但我的要求是“我们不应该在 src 子目录中有一个 sconscript 文件”你能告诉我只有一个 sconstruct 文件将如何编译所有源子目录吗?可以举个例子吗谢谢
  • @SrinivasReddy,我创建了另一个答案,以免将所有内容混合在一个答案中。我在另一个答案中举了一个只有一个 SConstruct 的例子。
猜你喜欢
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 2014-12-19
  • 2013-10-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多