【问题标题】:force target_link_libraries to use c++ linker强制 target_link_libraries 使用 c++ 链接器
【发布时间】:2015-02-25 20:11:32
【问题描述】:

TL;DR

在将静态 c++ 库链接到 c 可执行文件时,有没有办法强制 cmake 使用 c++ 链接器?


我有一个静态库,其中包含 2 个对象、一个 C++ 文件和该文件中函数的 C 包装器(构造函数、析构函数和打印函数),类似于 this SO 答案。最后一段说:

现在有趣的部分是确保您将所有必需的 C++ 库正确链接到更大的库中。对于 gcc(或 clang),这意味着只使用 g++ 进行最后的链接阶段。

我可以用我的 MCVE 验证这一点。用g++ 替换gcc 可以解决问题,一切正常

$ gcc -static main.c -L. -lCPPclass -o main
./libCPPclass.a(CInt.o): In function `newCINT':
CInt.cpp:(.text+0xd): undefined reference to `operator new(unsigned long)'
CInt.cpp:(.text+0x28): undefined reference to `operator delete(void*)'
./libCPPclass.a(CInt.o): In function `delCINT':
CInt.cpp:(.text+0x5e): undefined reference to `operator delete(void*)'
./libCPPclass.a(CInt.o):(.eh_frame+0x13): undefined reference to `__gxx_personality_v0'
./libCPPclass.a(CPPclass.o): In function `CPPclass::print_success()':
CPPclass.cpp:(.text+0x26): undefined reference to `std::cout'
CPPclass.cpp:(.text+0x2b): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
./libCPPclass.a(CPPclass.o): In function `__static_initialization_and_destruction_0(int, int)':
CPPclass.cpp:(.text+0x54): undefined reference to `std::ios_base::Init::Init()'
CPPclass.cpp:(.text+0x63): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
$
$#REPLACE gcc with g++
$
$ g++ -static main.c -L. -lCPPclass -o main
$ ./main
Success!

然而,我的真实代码是使用 CMake 构建的,因此我尝试使用 CMake 构建这个 MCVE,这让我回到了最初的问题。我的 CMakeLists.txt 文件如下:

cmake_minimum_required(VERSION 2.8)
project(Cmain C CXX)

add_library(CPPclass STATIC IMPORTED)
set_property(TARGET CPPclass PROPERTY IMPORTED_LOCATION ./libCPPclass.a)
add_executable(main main.c)
target_link_libraries(main CPPclass)

但是,当我运行 cmake . 然后运行 ​​make 时,我得到与上述相同的错误

$ cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/temp
$ make
Linking C executable main
./libCPPclass.a(CInt.o): In function `newCINT':
CInt.cpp:(.text+0xd): undefined reference to `operator new(unsigned long)'
CInt.cpp:(.text+0x28): undefined reference to `operator delete(void*)'

等等。当然,如果我将 main.c 重命名为 main.cpp,CMake 将使用 g++ 编译可执行文件,并且 target_link_libraries 将毫无错误地执行,但这有点违背 c 包装器的目的,并且在我的实际用例中不起作用。

【问题讨论】:

  • g++ 不使用不同的链接器——它只是添加一些默认库来链接到要链接的库列表。尝试将libstdc++ 库添加到您的target_link_libraries
  • @BillyONEal 感谢您为我澄清这一点。您的建议为我的 MCVE 和我的真实用例修复了它。如果您认为该问题仍然有效且有用,请将您的评论重写为答案,否则我愿意撤回它。
  • 请随意在答案中发布您所做的具体事情——您可以回答自己的事情。将来可能会帮助某人。我没有把它写成答案,因为我从来没有真正做过;只是在黑暗中拍摄。
  • @BillyONEal 会做,只是想在应得的地方给予荣誉。
  • 我有足够的无意义的网点:)

标签: c++ cmake


【解决方案1】:

在您的目标上将链接器语言设置为 CXX

set_target_properties(my_target PROPERTIES LINKER_LANGUAGE CXX)

我认为这比stdc++ 答案更好,因为它是通用的(我目前正在处理clang 的libc++)。这可能并不比IMPORTED_LINK_INTERFACE_LANGUAGES 的答案好,但肯定更直接。

【讨论】:

    【解决方案2】:

    这样做:

    set_target_properties(CPPclass PROPERTIES
      IMPORTED_LOCATION ./libCPPclass.a
      IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
    )
    

    【讨论】:

    • 有什么理由这是比另一个更好的答案,还是只是另一种做事方式?
    • 这是更好的答案,因为它是 cmake 命令 export()install(EXPORT) 生成的,并且因为它是一个抽象,而不是实现细节(因为要链接的 stdlib 是 - g++ 驱动程序不仅如此)。这个答案是正确的。
    【解决方案3】:

    正如上面 cmets 中提到的@BillyONEal,我不需要不同的链接器来获取所需的其他库,我只需将 libstdc++ 添加到要链接的库列表中。

    cmake_minimum_required(VERSION 2.8)
    project(Cmain C CXX)
    
    add_library(CPPclass STATIC IMPORTED)
    set_property(TARGET CPPclass PROPERTY IMPORTED_LOCATION ./libCPPclass.a)
    add_executable(main main.c)
    target_link_libraries(main CPPclass stdc++)
    

    【讨论】:

      猜你喜欢
      • 2019-03-09
      • 1970-01-01
      • 2011-07-20
      • 2014-08-01
      • 2016-09-30
      • 2012-10-07
      • 2022-12-04
      • 2017-10-08
      • 1970-01-01
      相关资源
      最近更新 更多