【发布时间】:2019-02-01 22:34:07
【问题描述】:
背景 我有一个使用其他较小项目的项目。这些项目本身是由其他项目组成的。其中很多是遗留问题或有其他管理命令的原因按原样安排,因此将所有内容整合到一个项目中不是一种选择。一些库是在远程共享上预编译的。
我有两个让我头疼的主要子项目:
Project Foo 是链接多个静态子项目(
foo_subproject_1、foo_subproject_n)的可执行文件和库。这些子项目进一步链接到远程位置的静态库(some_lib、some_other_lib)。 Project Foo 的可执行文件可以正确编译、链接和运行Project Bar 是一个可执行文件,可链接多个其他项目,包括 libFoo。链接失败,“未定义对”
foo_subproject函数的引用
据我所知,这两个项目的排列方式与它们的链接说明相似。看着 SO,我发现将静态库与静态库链接 shouldn't work,但后来我对如何成功编译 Project Foo 感到困惑。
gcc 和 g++ 4.9.2 是编译器(已经检查了 C 中的某些部分和 C++ 中的某些部分的外部“C”问题)
问题
我对 CMake add_subdirectory 的工作方式或链接器的工作方式中的一个或两个有误解。有人可以解释一下 Project Foo 是如何成功工作的,而 Project Bar(没有)按预期工作吗?
更新我仔细查看了 foo_lib.a 和 foo_runtime。
我应该从一开始就确定有什么问题,因为 foo_runtime 的大小接近 100MB,而 foo_lib 只有 10KB。
nm 表明 foo_lib.a 引用了几十个符号,其中大部分是未定义的。 foo_runtime 同时引用一切。
同样令人困惑的是 foo_subproject_1.a 也大多是未定义的。同样,这是我期望看到的;但我不明白如何由此构建 foo_runtime?
我仍然不清楚为什么some_library -> subproject -> foo_runtime 成功,但some_library -> subproject -> foo_lib -> bar 没有。在我调查的这个阶段,我预计这两个命令都会失败。
Project Foo是这样安排的(使用CMake):
cmake_minimum_required(VERSION 2.6)
project(foo)
set(FOO_SRCS
# source and headers for main foo project
)
# Project Foo libraries are subdirectories within this project
add_subdirectory(subs/foo_subproject_1)
add_subdirectory(subs/foo_subproject_2)
# Runtime executable
add_executable(foo_runtime main.c ${FOO_SRCS})
target_link_libraries(foo_runtime foo_subproject_1 foo_subproject_2)
# Library version (static library)
add_library(foo_lib STATIC ${FOO_SRCS})
target_link_libraries(foo_lib foo_subproject_1 foo_subproject_2)
Project Foo 的子目录大致具有以下架构:
cmake_minimum_required(VERSION 2.6)
project(foo_subproject_<n>)
set(FOO_SUBPROJECT_<N>_SRCS
# source and headers for subproject
)
# foo_subproject's remote libraries are all static
add_library(some_lib STATIC IMPORTED)
set_target_properties(some_lib PROPERTIES IMPORTED_LOCATION /path/to/libsome_lib.a)
add_library(some_other_lib STATIC IMPORTED)
set_target_properties(some_other_lib PROPERTIES IMPORTED_LOCATION /path/to/libsome_other_lib.a)
include_directories(/paths/to/libs/include/)
# Static library for foo_subproject_N, links against static libs above
add_library(foo_subproject_<N> STATIC ${FOO_SUBPROJECT_<N>_SRCS})
target_link_libraries(foo_subproject_<N> some_library some_other_library)
项目栏是这样排列的:
cmake_minimum_required(VERSION 2.6)
project(bar)
set(BAR_SRCS
# source and headers for main bar project
)
# Project Bar libraries are remote from Bar's perspective
add_library(foo_lib STATIC IMPORTED)
set_target_properties(foo_lib PROPERTIES IMPORTED_LOCATION /path/to/foo/libfoo_lib.a)
include_directories(/path/to/foo/include/)
# Runtime executable
add_executable(bar main.c ${BAR_SRCS} foo_lib)
Project Bar 无法链接(编译正常)并出现多个表单错误:
bar_frobulator.cpp:123: undefined reference to 'foo_subproject_1_init_frobulation'
foo_subproject_1_init_frobulation 位于 foo_subproject_1 中的位置
【问题讨论】:
-
库的顺序可能很重要。如果 A 库需要 B 库中的项目,则 B 库应放在 A 库之后。
-
@john 我认为这不是问题所在。 Foo 的子项目以正确的顺序拥有它们的库,但子项目并不相互依赖,因此对 Foo 无关紧要。 Bar 的库也是独立的(为简洁起见,此处仅显示了 foo_lib,但没有一个库是相互连接的)
-
不是你需要明确包含 foo 子项目库的答案吗?如果我正确阅读了上述内容,那么您只是在链接 foo 项目而不是子项目。
-
@john 也许(但如果属实,Bar 阶段最终会有很多东西要链接,所以如果可以的话,我宁愿避免这种情况) .如果为真,为什么 Foo 运行时有效?它不链接到 some_library (它的子项目这样做),但愉快地调用这些函数。为什么这对 Foo 有效,但对 Bar 无效?
-
在
Foo项目中,您以一种令人困惑的方式使用add_executable:通过在add_executable调用中列出foo_subproject_1,您(可能)期望链接,但是这种形式只暗示文件依赖,而不是链接。要链接可执行文件,请使用target_link_libraries(foo_runtime foo_subproject_1)。add_library调用也存在类似问题。在当前的表格中,我看不出Foo和Bar项目之间没有任何关系,我们可以比较一下:它们是完全不同的项目,它们链接不同的库。