静态库通过CMake与其他静态库链接-一种有效,一种无效.为什么? [英] Static libraries linked against other static libraries with CMake - one works, one doesn't. Why?
问题描述
背景 我有一个使用其他较小项目的项目.这些项目本身由其他项目组成.其中很多是遗留的,或者按原样安排还有其他管理上的原因,因此将所有内容都滚动到一个项目中是不可行的.有些库是在远程共享上预编译的.
Background I have a project that uses other smaller projects. These projects themselves are made of other projects. A lot of this is legacy or has other managerial-fiat reasons for being arranged as is, so rolling everything into a single project is not an option. Some libraries are pre-compiled on remote shares.
我有2个主要的子项目让我头疼:
I have 2 main subprojects that are giving me a headache:
-
Project Foo 是链接几个静态子项目(
foo_subproject_1
,foo_subproject_n
)的可执行文件和库.这些子项目进一步链接到远程位置(some_lib
,some_other_lib
)中的静态库. Project Foo的可执行文件正确编译,链接并运行
Project Foo is an executable and library that links several static subprojects (
foo_subproject_1
,foo_subproject_n
). These subprojects are further linked against static libraries in remote locations (some_lib
,some_other_lib
). Project Foo's executable compiles, links, and runs correctly
项目栏是一个可执行文件,可以链接几个其他项目,包括libFoo.链接失败,并带有对foo_subproject
函数的未定义引用
Project Bar is an executable that links several other projects, including libFoo. Linking fails with "undefined reference to " foo_subproject
functions
据我所知,这两个项目的排列方式与它们的链接说明相似.如此看来,我发现将静态库与静态库链接工作,但随后我对如何成功编译Project Foo感到困惑.
As far as I can tell, the two projects are arranged similarly with their linkage instructions. Looking on SO, I discover that linking static libraries against static libraries shouldn't work, but then I'm confused as to how Project Foo is compiled successfully.
gcc和g ++ 4.9.2是编译器(已经在C中包含某些部分,而在C ++中具有某些部分的外部"C"问题)
gcc and g++ 4.9.2 are the compilers (extern "C" problems of having some parts in C and some in C++ have already been checked for)
问题
我对CMake add_subdirectory的工作方式或链接器的工作方式误解了.有人可以解释一下Foo项目是如何成功工作的,而Project Bar(不是)是按预期的工作吗?
I have misunderstood something about either or both how CMake add_subdirectory works, or about how the linker works. Can someone please explain how Project Foo works successfully, and Project Bar (doesn't) works as expected?
更新:我仔细查看了foo_lib.a和foo_runtime.
Update I looked closer at foo_lib.a and foo_runtime.
我本来应该确定一开始是不可能的,因为foo_runtime的大小接近100MB,而foo_lib仅为10KB.
I should have determined that something was off to start with, because foo_runtime is nearly 100MB in size, and foo_lib is only 10KB.
nm
显示foo_lib.a引用了几十个符号,其中大多数未定义. foo_runtime同时引用所有内容.
nm
reveals that foo_lib.a references a few dozen symbols, most of which are undefined. foo_runtime meanwhile references everything.
同样令人困惑的是,foo_subproject_1.a同样几乎是未定义的.再次,这是我期望所见;但我不明白如何从中构建foo_runtime?
Equally confusing is that foo_subproject_1.a is similarly mostly undefined. Again, this is what I expect to see; but I don't understand how foo_runtime can be built from this?
我仍然不清楚为什么some_library -> subproject -> foo_runtime
成功,但是some_library -> subproject -> foo_lib -> bar
没有成功.在调查的这个阶段,我期望这两个命令都会失败.
I'm still unclear as to why some_library -> subproject -> foo_runtime
is successful, but some_library -> subproject -> foo_lib -> bar
isn't. At this stage of my investigations, I am expecting both commands to fail.
Foo项目的安排如下(使用CMake):
Project Foo is arranged (using CMake) thusly:
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)
Foo项目的子目录大致具有以下架构:
Project Foo's subdirectories loosely have the following architecture:
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)
项目栏的排列方式如下:
Project Bar is arranged thusly:
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无法链接(编译成功)并出现以下形式的多个错误:
Project Bar fails to link (compiles ok) with multiple errors of the form:
bar_frobulator.cpp:123: undefined reference to 'foo_subproject_1_init_frobulation'
foo_subproject_1_init_frobulation
所在的foo_subproject_1
where foo_subproject_1_init_frobulation
lives in foo_subproject_1
推荐答案
有人可以解释一下Project Foo如何成功工作,而Project Bar(没有)按预期工作吗?
Can someone please explain how Project Foo works successfully, and Project Bar (doesn't) works as expected?
简而言之:创建STATIC库不涉及链接步骤!
In short: Creating STATIC library doesn't involve linking step!
在Foo项目中,您有一个可执行文件foo_runtime
,该文件起作用"是因为它与适当的库链接在一起(例如,与定义了foo_subproject_1_init_frobulation
符号的库foo_subproject_1
链接).
In the Foo project you have an executable foo_runtime
, which "works" because it is linked with proper libraries (e.g. with library foo_subproject_1
which defines foo_subproject_1_init_frobulation
symbol).
Bar项目中的可执行文件bar
不执行该链接,因此失败.线
An executable bar
from Bar project doesn't perform that linking, so it fails. The line
target_link_libraries(bar foo_lib)
与foo_lib
链接,但是该库未定义所需的符号foo_subproject_1_init_frobulation
.
links with foo_lib
, but this library doesn't defines the needed symbol foo_subproject_1_init_frobulation
.
请注意,该行
target_link_libraries(foo_lib foo_subproject_1 foo_subproject_2)
Foo项目中的
不执行实际的链接:通常,构建静态库不涉及链接步骤.
in the Foo project doesn't perform actual linking: in general, building a static library doesn't involve linking step.
仅将传播行包括从foo_subproject_*
库到foo_lib
一个的目录(以及其他编译功能).
Given line just propagates include directories (and other compile-features) from foo_subproject_*
libraries to the foo_lib
one.
因为静态库foo_lib
不跟踪其依赖关系,所以您需要将bar
链接到知道这一点的库.例如,根据引用的问题
Because static library foo_lib
doesn't track its dependency, you need to link bar
with a library, which knows that. E.g., make foo_lib
shared, or combine foo_subproject_*
libraries into archive library, as suggested by the referenced question How to combine several C/C++ libraries into one?.
或者,您可以在Bar
项目中构建一个Foo
子项目,而不是创建在Foo
项目中创建的普通" foo_lib
目标,而不是创建IMPORTED foo_lib
目标.在这种情况下,第
Alternatively, you may build Foo
subproject within Bar
one and, instead of creation of IMPORTED foo_lib
target, use "normal" foo_lib
target, created within Foo
project. In that case, line
target_link_libraries(bar foo_lib)
意味着CMake(实际上)将bar
与foo_subproject_*
库链接在一起,因为这些库被链接"(在CMake的意义上)到foo_lib
中.同样,最后一个链接"仅对CMake有意义:文件foo_lib.a
并不知道需要foo_subproject_*
库.
would mean for CMake to (actually) link bar
with foo_subproject_*
libraries, because those libraries are "linked" (in CMake sense) into foo_lib
. Again, the last "linking" has a meaning only for CMake: the file foo_lib.a
doesn't aware about needing of foo_subproject_*
libraries.
这篇关于静态库通过CMake与其他静态库链接-一种有效,一种无效.为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!