强制target_link_libraries使用c ++链接器

时间:2015-02-25 20:11:33

标签: c++ cmake

TL; DR

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


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

  

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

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

$ 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包装器的用途并且无法工作我的真实用例。

3 个答案:

答案 0 :(得分:2)

在目标

上将链接器语言设置为CXX
set_target_properties(my_target PROPERTIES LINKER_LANGUAGE CXX)

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

答案 1 :(得分:1)

这样做:

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

答案 2 :(得分:0)

正如@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++)