Kid*_*ris 5 c++ linker g++ cmake
背景 我有一个使用其他较小项目的项目。这些项目本身由其他项目组成。其中很多是遗留的,或者按原样安排还有其他管理上的原因,因此将所有内容都滚动到单个项目中是不可行的。有些库已在远程共享上进行了预编译。
我有两个让我头疼的主要子项目:
FOO项目是一个可执行文件和库链接几个静态子项目(foo_subproject_1,foo_subproject_n)。这些子项目针对远程位置的静态库进一步连接(some_lib,some_other_lib)。Project Foo的可执行文件可以正确编译,链接和运行
Project Bar是可执行文件,可链接其他几个项目,包括libFoo。链接失败,并带有“对foo_subproject函数的未定义引用”
据我所知,这两个项目的链接说明相似。从SO的角度来看,我发现将静态库与静态库链接不起作用,但是对于如何成功编译Project Foo感到困惑。
gcc和g ++ 4.9.2是编译器(已经检查了C中有某些部分,C ++中有一些部分的外部“ C”问题)
题
我对CMake add_subdirectory的工作方式或链接程序的工作方式或两者都有误解。有人可以解释一下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没有成功。在调查的这个阶段,我期望这两个命令都会失败。
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)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
项目栏就这样排列:
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)
Run Code Online (Sandbox Code Playgroud)
Project Bar无法链接(编译成功)并出现以下形式的多个错误:
bar_frobulator.cpp:123: undefined reference to 'foo_subproject_1_init_frobulation'
Run Code Online (Sandbox Code Playgroud)
其中,foo_subproject_1_init_frobulation住在foo_subproject_1
有人可以解释一下Foo项目是如何成功工作的,而Project Bar(不是)是按预期的工作方式吗?
简而言之:创建STATIC库不涉及链接步骤!
在Foo项目中,您有一个可执行文件foo_runtime,之所以“有效”是因为它与适当的库(例如foo_subproject_1,定义foo_subproject_1_init_frobulation符号的库)链接。
barBar项目中的可执行文件不会执行该链接,因此会失败。线
target_link_libraries(bar foo_lib)
Run Code Online (Sandbox Code Playgroud)
与链接foo_lib,但此库未定义所需的符号foo_subproject_1_init_frobulation。
注意,那行
target_link_libraries(foo_lib foo_subproject_1 foo_subproject_2)
Run Code Online (Sandbox Code Playgroud)
在Foo项目中,不执行实际的链接:通常,构建静态库不涉及链接步骤。
给定的行只是将包含目录(和其他编译功能)的内容从foo_subproject_*库传播到foo_lib一个库。
由于静态库foo_lib不会跟踪其依赖关系,因此您需要链接bar一个知道这一点的库。例如,如参考问题所述,建议foo_lib将foo_subproject_*库共享或合并到存档库中如何将多个C / C ++库合并到一个库中?。
或者,您可以Foo在Bar一个项目中构建子项目,而不foo_lib使用foo_lib创建Foo项目中创建的“正常” 目标来代替创建导入目标。在这种情况下,
target_link_libraries(bar foo_lib)
Run Code Online (Sandbox Code Playgroud)
这意味着CMake(实际上)bar与foo_subproject_*库链接,因为这些库(在CMake的意义上)“链接”到foo_lib。同样,最后的“链接”仅对CMake有意义:该文件foo_lib.a不知道需要foo_subproject_*库。
| 归档时间: |
|
| 查看次数: |
1296 次 |
| 最近记录: |