静态库通过CMake与其他静态库链接-一种有效,一种无效.为什么? [英] Static libraries linked against other static libraries with CMake - one works, one doesn't. Why?

查看:118
本文介绍了静态库通过CMake与其他静态库链接-一种有效,一种无效.为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景 我有一个使用其他较小项目的项目.这些项目本身由其他项目组成.其中很多是遗留的,或者按原样安排还有其他管理上的原因,因此将所有内容都滚动到一个项目中是不可行的.有些库是在远程共享上预编译的.

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_1foo_subproject_n)的可执行文件和库.这些子项目进一步链接到远程位置(some_libsome_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(实际上)将barfoo_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆