可能是我能想到的最短的工作示例:
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(相同内容):
#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" #includevoid doit(void) { printf("doit"); }
系统:
Ubunto 15.10
gcc 5.2.1/clang 3.6.2(试过)
CMake 3.2.2
当我这样做时make myprog
,myprog
链接阶段抱怨有一个未定义的引用doit
.但是,如果我使用make myprog2
,一切都正确链接,程序按预期运行.
我不明白为什么CMake没有正确mylib
地在C++程序中正确链接.从编译器获得详细的输出(我已经修剪了一些到系统库路径/目标文件的链接):
"/ 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
奇怪的是,它没有使用a -lmylib
来链接mylib.我得到了类似的输出myprog2
.
我的问题是为什么会发生这种情况,更重要的是,我如何myprog
正确链接到mylib
?
你需要在c ++中声明c函数extern "C"
.例如,c ++编译器更改函数名称以允许函数重载
int function(int value);
和
int function(char *value);
两者都可以用完全相同的名称在c ++中定义,编译器将生成两个具有不同名称的不同函数,以使其正常工作.
在c中,您无法执行此操作,并且不需要修改函数名称.通过使用extern "C"
您可以防止编译器更改函数名称,因此链接阶段将按预期工作.
要修复它,请以这种方式启动main.cpp:
extern "C" { #include "mylib.h" }