背景
要把内核的一部分逻辑抽象成动态库,尝试写demo加载的时候一直链接不上,写此帖记录!以及过程中出现的问题原因!!!(见下文tips)
假设我的动态库代码长这个样子:
//a.h
#ifndef AAA
#define AAA
void yzy(int a);
#endif
//a.c
#include <stdio.h>
#include "a.h"
void yzy(int a) {
printf("a is : %d\n", a);
return;
}
CMakeLists.txt写这样
project(aaa)
cmake_minimum_required(VERSION 2.8)
aux_source_directory(./ SRC)
add_library(${PROJECT_NAME} SHARED ${SRC})
这段代码可以编译出来动态库libaaa.so
其他程序如果想链接这个动态库,可以用下面的CMakeLists.txt逻辑
假设我新写了一个main.c
#include <stdio.h>
#include "a.h"
int main() {
yzy(2);
return 0;
}
用下面的CMakeLists.txt 就可以链接
project(main)
cmake_minimum_required(VERSION 2.8)
#这个是动态库头文件路径,在下面target_include_directories用到
set(SDK_INC /home/liar/code/sdk)
aux_source_directory(./ SRC)
#重要!,这里链接第三方动态库,要写在add_executable的前面
link_libraries(${SDK_INC}/build/libaaa.so)
add_executable(main ${SRC})
target_include_directories(main
PUBLIC ${SDK_INC})
注意事项 tips
-
link_libraries要写在add_executable或者add_library的前面
-
nm命令可以查看二进制程序或者动态库的符号表,gcc和g++编译出来的符号是不一样的,gcc编译出来的符号,就是函数名,g++编译出来的符号会在函数名前后进行一些字符拼接
[liar@localhost /home/liar/code/sdk/build]$ nm libaaa.so
0000000000201030 B __bss_start
0000000000201030 b completed.6355
w __cxa_finalize@@GLIBC_2.2.5
00000000000005d0 t deregister_tm_clones
0000000000000640 t __do_global_dtors_aux
0000000000200df0 t __do_global_dtors_aux_fini_array_entry
0000000000200e00 d __dso_handle
0000000000200e08 d _DYNAMIC
0000000000201030 D _edata
0000000000201038 B _end
00000000000006dc T _fini
0000000000000680 t frame_dummy
0000000000200de8 t __frame_dummy_init_array_entry
0000000000000770 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
00000000000006f0 r __GNU_EH_FRAME_HDR
0000000000000568 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000200df8 d __JCR_END__
0000000000200df8 d __JCR_LIST__
w _Jv_RegisterClasses
U printf@@GLIBC_2.2.5
0000000000000600 t register_tm_clones
0000000000201030 d __TMC_END__
00000000000006b5 T yzy
上面最后一行函数yzy就是gcc编译出来的,可以看到符号名和函数名是一样的
下面我们用g++编译一下动态库set(CMAKE_C_COMPILER "/usr/bin/g++")
[liar@localhost /home/liar/code/sdk/build]$ nm libaaa.so
0000000000201030 B __bss_start
0000000000201030 b completed.6355
w __cxa_finalize@@GLIBC_2.2.5
00000000000005f0 t deregister_tm_clones
0000000000000660 t __do_global_dtors_aux
0000000000200dc0 t __do_global_dtors_aux_fini_array_entry
0000000000200dd0 d __dso_handle
0000000000200dd8 d _DYNAMIC
0000000000201030 D _edata
0000000000201038 B _end
00000000000006fc T _fini
00000000000006a0 t frame_dummy
0000000000200db8 t __frame_dummy_init_array_entry
0000000000000790 r __FRAME_END__
0000000000201000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000000710 r __GNU_EH_FRAME_HDR
0000000000000590 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000200dc8 d __JCR_END__
0000000000200dc8 d __JCR_LIST__
w _Jv_RegisterClasses
U printf@@GLIBC_2.2.5
0000000000000620 t register_tm_clones
0000000000201030 d __TMC_END__
00000000000006d5 T _Z3yzyi
可以看到最后一行的符号名字不再是yzy了。
有一次遇到了undefined reference to xxx
就是因为编译动态库使用了g++,编写main程序用了gcc,导致main程序找不到动态库中的符号。