【问题标题】:CMake is not linking library as expected (How to force linking) [duplicate]CMake未按预期链接库(如何强制链接)[重复]
【发布时间】:2019-11-23 20:19:55
【问题描述】:

情况:

假设我有 2 个库(libA.a、libB.a)我想在可执行文件 (exec.cpp) 中使用。 我的libA 包括在libB 的函数bar(y) 中使用的foo(x)。因此,我在libB 中包含libA 的标头,然后在我的可执行文件中包含libB 的标头并链接两者:

A.h:

#ifndef LIB_A_INCLUDED
#define LIB_A_INCLUDED

int foo(int x);

#endif

A.cpp:

int foo(int x) {
    //DO stuff
}

B.h

#ifndef LIB_B_INCLUDED
#define LIB_B_INCLUDED

#include <A.h>

int bar(int y);

#endif

B.cpp:

int bar(int y) {
    foo(y);
    //more stuff
}

两个库的 CMakeLists 文件如下所示(对于 libB,还有一个 include_directories 调用以包含 A.h):

cmake_minimum_required(VERSION 3.15)
project(libA)

set(CMAKE_CXX_STANDARD 14)

add_library(libA A.h A.c)

Exec.cpp:

#include<B.h>

int main() {
    bar(42);
    return 0;
}

可执行文件的 CMakeLists 文件如下所示:

cmake_minimum_required(VERSION 3.15)
project(Exec)

set(CMAKE_CXX_STANDARD 14)
include_directories("PATH_TO_HEADER_A/A.h" "PATH_TO_HEADER_B/B.h")

add_executable(Exec main.cpp)

target_link_libraries(Exec "PATH_TO_LIB_A/libA.a;PATH_TO_LIB_B/libB.a")

问题

这不起作用!它产生:

/usr/bin/ld: PATH_TO_LIB_B/libB.a(B.c.o): in function `bar':

/usr/bin/ld: PATH_TO_LIB_B/B.cpp:95: undefined reference to `foo'

但是,当我将 Exec.cpp 更改为:

#include<B.h>

int main() {
    bar(42);
    foo(31415);
    return 0;
}

它按预期编译和工作 - 当 exec.cpp 中没有直接使用 libA 的函数时,链接器似乎没有链接 libA,即使这些函数在 @ 中使用987654342@ 肯定是使用foo

问题

有没有办法强制链接?我如何让它发挥作用?

【问题讨论】:

  • 图书馆的链接顺序很重要,请参阅重复问题的答案:stackoverflow.com/questions/12573816/…
  • 那么正确的顺序是什么?因为我确实考虑了顺序 - 这就是为什么 libA 在 target_link_libraries 列表中排在第一位的原因。对我来说这是有道理的,为什么会出现这种情况,但不应该首先链接“较低”(在我的情况下是 libA,因为它在 libB 中使用,而它又被可执行文件使用)库?另外,为什么我在可执行文件中使用“foo(x)”而不更改其他任何内容时它会起作用?
  • 引用答案的引用:“一般来说,如果库 A 依赖于库 B,则 libA 必须出现在链接器标志中的 libB 之前。”。在您的情况下,libB 依赖于libA,因此libB 应该在target_link_libraries 调用中之前 libA

标签: c++ cmake linker


【解决方案1】:

您的libB 不知道foo 的实现(提供libA 的标头是不够的)。解决此问题的一种方法是在libB CMake 文件中使用target_link_libraries()libA 链接到libB。您可以将 libB CMake 更改为如下所示:

cmake_minimum_required(VERSION 3.15)
project(libB)

set(CMAKE_CXX_STANDARD 14)

add_library(libB B.h B.cpp)
target_include_directories(libB PUBLIC PATH_TO_HEADER_A)    
target_link_libraries(libB PUBLIC "PATH_TO_LIB_A/libA.a")

根据反馈,根据链接的重复问题添加一个示例,显示链接器的顺序很重要。看起来每个库都是由一个单独的 CMake 实例构建的,所以这可能更相关;可执行文件的 CMake 应重新排序链接库以首先放置 libB。 (另外,从include_directories() 调用中删除标头名称,因为这不是必需的。):

cmake_minimum_required(VERSION 3.15)
project(Exec)

set(CMAKE_CXX_STANDARD 14)
include_directories(PATH_TO_HEADER_A PATH_TO_HEADER_B)

add_executable(Exec main.cpp)

target_link_libraries(Exec PATH_TO_LIB_B/libB.a PATH_TO_LIB_A/libA.a)

【讨论】:

  • 由于这是互联网上许多类似问题的第一个答案,我已经尝试过(几乎所有可能的排列方式)。 这并不能解决问题。
  • @The_Reto 好的,如果您在单独的 CMake 实例中创建每个库(分别运行 CMake 三次,但我扩展了答案以包括在链接的重复问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
相关资源
最近更新 更多