gpt4 book ai didi

c++ - scons、CPPPATH 和多个库

转载 作者:行者123 更新时间:2023-11-30 05:21:00 27 4
gpt4 key购买 nike

问题描述

我正在尝试使用 scons 构建一个模块化系统来编译多个共享库,其中一些共享库依赖于其他共享库。虽然我可以使用一些不同的变通办法来编译它,但每个变通办法都有一些缺点,如“尝试的解决方案”部分所述。

.
├── SConstruct
└── src
├── libA
│   ├── a.cc
│   ├── a.hh
│   └── SConscript
├── libB
│   ├── b.cc
│   ├── b.hh
│   └── SConscript
└── SConscript

这里,b.cc包含了a.hh,这是两个库之间的依赖关系。

每个文件的内容如下所示。

# In SConstruct
VariantDir('build', 'src', duplicate=False)
SConscript('build/SConscript')

# In src/SConscript
env = Environment()
SConscript(['libA/SConscript', 'libB/SConscript'],
exports='env')

# In src/libA/SConscript
Import('env')

env.Append(CPPPATH=['.'])
env.SharedLibrary('a.cc')

# In src/libB/SConscript
Import('env')

env.Append(CPPPATH=['.'])
env.SharedLibrary('b.cc')

在这里,我遇到了一个问题。当我运行 scons 时,我得到以下结果。

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o build/libA/a.os -c -fPIC -Ibuild/libA -Isrc/libA -Ibuild/libA -Isrc/libA src/libA/a.cc
g++ -o build/libA/liba.so -shared build/libA/a.os
g++ -o build/libB/b.os -c -fPIC -Ibuild/libB -Isrc/libB -Ibuild/libB -Isrc/libB src/libB/b.cc
src/libB/b.cc:3:16: fatal error: a.hh: No such file or directory
#include "a.hh"
^
compilation terminated.
scons: *** [build/libB/b.os] Error 1
scons: building terminated because of errors.

我从this older question知道-Ibuild/libA-Isrc/libA 的重复是有意义的,并且是有意的。但是-Isrc/libA在编译a.cc时被传递了两次,在编译b.cc时根本没有传递。


尝试的解决方案

这似乎是由于将字符串传递到 CPPPATH 而不是 Dir() 节点引起的。该字符串稍后会使用当前 SConscript 的路径进行扩展,而不是使用当前 SConscript 进行扩展。为了避免这种情况,我在 src/libA/SConscript 中将 CPPPATH=['.'] 修改为 CPPPATH=[Dir('.')] > 和 src/libB/SConscript。这不起作用,因为只有 build/libA 包含在 CPPPATH 中,而不是 src/libA,如下所示。

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o build/libA/a.os -c -fPIC -Ibuild/libA -Ibuild/libB src/libA/a.cc
g++ -o build/libA/liba.so -shared build/libA/a.os
g++ -o build/libB/b.os -c -fPIC -Ibuild/libA -Ibuild/libB src/libB/b.cc
src/libB/b.cc:3:16: fatal error: a.hh: No such file or directory
#include "a.hh"
^
compilation terminated.
scons: *** [build/libB/b.os] Error 1
scons: building terminated because of errors.

其次,我使用 duplicate=False 对此进行了测试。结合第一个测试,使用 Dir('.'),这成功编译了库。然而,这并不理想,因为任何调试符号都会指向 build 目录中的源文件。对于大型项目,编译后,我喜欢删除 build 目录以节省空间,这会使调试变得更加困难,因为 gdb 无法再找到源文件。

接下来,我尝试使用绝对路径。也就是说,在 libA 中,我添加了 CPPPATH=['#/src/libA'],在 libB 中,我添加了 CPPPATH=['#/src/libB']。编译成功,duplicate=False。但是,这旨在作为一个库,可能包含在许多不同的顶级 SConstructs 中。通过将路径硬编码到库的 SConscript 中,它限制了该库的使用。

最后,我尝试完全不使用 VariantDir。除了使用 Dir('.') 作为每个库的路径之外,这还有效,但会将所有中间文件留在 src 目录中。这会弄乱目录结构,并使维护多个构建(例如调试/发布)变得非常棘手。

是否有可以避免这些问题的设计用法?

最佳答案

您声明“通过将路径硬编码到库的 SConscript 中,它限制了该库的使用。”。但是有什么选择呢?在您的构建描述中的某个时刻,您必须具体说明应搜索哪些路径以查找隐式依赖项(如 header 或库)。如果您随后移动文件夹,构建将会中断...与您选择的构建工具无关。

使用从顶级 SConstruct 开始指定的 SCons“#”路径,效果很好,是您问题的一种解决方案。另一种选择是使用相对路径,从您当前的 SConstruct 向上或向下开始。所以对于 src/libB/SConscript 你可以使用:

Import('env')

env.AppendUnique(CPPPATH=['.', '../libA'])
env.SharedLibrary('b.cc')

这样至少可以让您将“libA”和“libB”同时移动到一个新位置。但我不认为你能做得比这更好......

关于c++ - scons、CPPPATH 和多个库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40424482/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com