强制 target_link_libraries 使用 C++ 链接器
force target_link_libraries to use c++ linker
TL;DR
在将静态 c++ 库链接到 c 可执行文件时,有没有办法强制 cmake 使用 c++ 链接器?
我有一个由 2 个对象组成的静态库,一个 C++ 文件和一个对该文件中函数(构造函数、析构函数和打印函数)的 C 包装器,类似于 this SO 答案。最后一段指出:
The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using 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 构建的,所以我试图让这个 MCVE 使用 CMake 构建,这让我回到了我最初的问题。我的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 包装器的目的并且不会在我的真实用例中工作。
正如@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++)
这样做:
set_target_properties(CPPclass PROPERTIES
IMPORTED_LOCATION ./libCPPclass.a
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
)
在您的目标上将链接器语言设置为 CXX
set_target_properties(my_target PROPERTIES LINKER_LANGUAGE CXX)
我认为这比 stdc++
的答案要好,因为它很笼统(我目前正在处理 clang 的 libc++)。它可能并不比 IMPORTED_LINK_INTERFACE_LANGUAGES
答案好,但肯定更直接。
TL;DR
在将静态 c++ 库链接到 c 可执行文件时,有没有办法强制 cmake 使用 c++ 链接器?
我有一个由 2 个对象组成的静态库,一个 C++ 文件和一个对该文件中函数(构造函数、析构函数和打印函数)的 C 包装器,类似于 this SO 答案。最后一段指出:
The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using 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 构建的,所以我试图让这个 MCVE 使用 CMake 构建,这让我回到了我最初的问题。我的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 包装器的目的并且不会在我的真实用例中工作。
正如@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++)
这样做:
set_target_properties(CPPclass PROPERTIES
IMPORTED_LOCATION ./libCPPclass.a
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
)
在您的目标上将链接器语言设置为 CXX
set_target_properties(my_target PROPERTIES LINKER_LANGUAGE CXX)
我认为这比 stdc++
的答案要好,因为它很笼统(我目前正在处理 clang 的 libc++)。它可能并不比 IMPORTED_LINK_INTERFACE_LANGUAGES
答案好,但肯定更直接。