TL;DR
Is there a way to force cmake to use the c++ linker when linking a static c++ library to a c executable?
I have a static library that consists of 2 objects, a C++ file and a C wrapper to the functions in that file (Constructor, Destructor, and Print function), similar to this SO answer. The last paragraph states:
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++.
I can verify this with my MCVE. Replacing gcc
with g++
fixes the problem and everything works
$ 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!
My real code, however, is built using CMake, so I'm trying to get this MCVE built with CMake, which takes me back to my original question. My CMakeLists.txt file is as follows:
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)
However, when I run cmake .
and then make
I get the same errors as above
$ 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*)'
etc. Of course if I renamed main.c
to main.cpp
, CMake would compile the executable with g++ and target_link_libraries would execute without error, but it kind of defeats the purpose of the c wrapper and doesn't work in my real use case.