Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake won't Link C library to C++ program

Probably the shortest working example I can think of:

CMakeLists.txt:

project(myprogs)
cmake_minimum_required(VERSION 2.8)

add_executable(myprog2 main.c)
add_executable(myprog main.cpp)
add_library(mylib SHARED mylib.c)

target_link_libraries(myprog2 mylib)
target_link_libraries(myprog mylib)

main.c/main.cpp (identical contents):

#include "mylib.h"

int main(int argc, char** argv)
{
  doit();
}

mylib.h:

#ifndef MYLIB_H
#define MYLIB_H

void doit(void);

#endif

mylib.c:

#include "mylib.h"
#include <stdio.h>

void doit(void)
{
  printf("doit");
}

System:

  • Ubunto 15.10
  • gcc 5.2.1/clang 3.6.2 (tried both)
  • CMake 3.2.2

When I do a make myprog, myprog's link phase complains that there is an undefined reference to doit. However, if I use make myprog2, everything links correctly and the program runs as expected.

I don't understand why CMake isn't properly linking to mylib correctly in the C++ program. Getting verbose output form the compiler gives (I've trimmed some of the linking to system library paths/object files):

"/usr/bin/ld" -export-dynamic --eh-frame-hdr -m elf_x86_64 -dyna mic-linker /lib64/ld-linux-x86-64.so.2 -o myprog CMakeFiles/myprog.dir/main.cpp.o libmylib.so -rpath /home/andrew/code/misc/myprog/build -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

Strangely, it's not using a -lmylib to link with mylib. I get a similar output for myprog2.

My question is why is this happening, and more importantly, how do I get myprog to properly link to mylib?

like image 840
helloworld922 Avatar asked Dec 22 '15 03:12

helloworld922


People also ask

Can I use Cpp library in C?

If the C++ compiler provides its own versions of the C headers, the versions of those headers used by the C compiler must be compatible. Oracle Developer Studio C and C++ compilers use compatible headers, and use the same C runtime library. They are fully compatible.

Can you use CMake with C?

In the C/C++ ecosystem, the best tool for project configuration is CMake. CMake allows you to specify the build of a project, in files named CMakeLists. txt, with a simple syntax (much simpler than writing Makefiles).

Is CMake C or C++?

Both C++ CMake tools for Windows and Linux Development with C++ are required for cross-platform CMake development.


1 Answers

You need to declare c functions with extern "C" in c++. The c++ compiler changes function names in order to allow function overloading, so for instance

int function(int value);

and

int function(char *value);

both can be defined in c++ with exactly the same name, the compiler will generate two different functions with different names for this to work correctly.

In c you can't do this, and the function name will not need to be modified. By using extern "C" you prevent the compiler from altering function names, and so the link phase will work as you expect it.

To fix it, start main.cpp this way:

extern "C" {
#include "mylib.h"
}
like image 192
Iharob Al Asimi Avatar answered Sep 26 '22 02:09

Iharob Al Asimi