cmake编译静态库
㈠ 如何才能使CMake生成的可执行程序便于调试
出现的原因是导入的此makefile工程不是debug模式的,所以不包含调试信息,自然不能打断点调试了。因此,要解决这个问题就要考虑如何修改CMakeLists.txt使其生成的makefile文件进而生成Debug模式下的带调试信息的可执行程序;
我们先写一个简单的测试例子来测试一下,如何加调试信息:
假设文件结构如下:
./test6
|
+ ------ CmakeLists.txt
+ ------ main.cpp
+ ------ src_a
|
+ ------ CmakeLists.txt
+ ------ Testa.h
+ ------ Testa.cpp
+ ------ src_so
|
+ ------ CmakeLists.txt
+ ------ Testso.h
+ ------ Testso.cpp
第一步:test6目录下CmakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(main )
add_subdirectory(src_a ) // 给当前工程目录添加子目录 src_a
add_subdirectory(src_so ) // 给当前工程目录添加子目录 src_so
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") //添加调试信息
set(EXECUTABLE_OUTPUT_PATH $ {PROJECT_SOURCE_DIR}/bin) //设置可执行文件的生成路径
include_directories($ {PROJECT_SOURCE_DIR}/src_a ${PROJECT_SOURCE_DIR}/src_so) //包含库头文件
aux_source_directory(. DIR_SRCS ) // 将当前目录中的源文件名称赋值给变量 DIR_SRCS
add_executable(main $ {DIR_SRCS}) //表示 DIR_SRCS中的源文件需要编译成名为 main的可执行文件
target_link_libraries (main Testa Testso) //将库文件链接到生成的目标可执行文件
第二步:子目录目录下CmakeLists.txt
1,src_a中静态库的编译生成
cmake_minimum_required(VERSION 3.3) //该命令限定了 CMake 的版本
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") //添加调试信息
set(LIBRARY_OUTPUT_PATH $ {PROJECT_SOURCE_DIR}/bin) //设置Lib 静态库生成路径
aux_source_directory(. LIBA_SRC) //将当前目录中的源文件名称赋值给变量 LIBA_SRC
add_library(Testad STATIC $ {LIBA_SRC}) //将变量 LIBA_SRC中的源文件编译为静态库,库文件名称为 Testa
2,src_so中动态库的编译生成
cmake_minimum_required(VERSION 3.3) //该命令限定了 CMake 的版本
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") //添加调试信息
set(LIBRARY_OUTPUT_PATH $ {PROJECT_SOURCE_DIR}/bin) //设置Lib 动态库库生成路径
aux_source_directory(. LIBSO_SRC) //将当前目录中的源文件名称赋值给变量 LIBA_SRC
add_library(Testsod SHARED $ {LIBSO_SRC}) //将变量 LIBA_SRC中的源文件编译为动态库,库文件名称为 Testso
此处执行cmake时有两种方式:
1,在cmake的gui界面中设定生成Debug模式,
2,在执行cmake时使用如下命令:cmake -DCMAKE_BUILD_TYPE=Debug/Release path
关于ccmake的使用,这里简单的做个说明:
1.首先在终端启动cmake的gui界面:"ccmake ." 效果如图:
2.然后在gui中输入"c",效果如图:
3.然后在gui中输入"e",效果如图:
4.此时在gui界面点击"enter"回车键进行编辑:编辑完再次点击回车退出编辑。
5.点击"c",之后再次点击"g"。此时makefile文件已经生成好了。make之后生成的可执行文件是带有调试信息的,就可用gdb进行调试了(导入Eclipse也可以进行打断点调试)。
㈡ windows下怎么使用cmake生成.a的静态库
您好,很高兴为您解答:
在使用cmake时,CMakeLists.txt的写法如下: add_library( ${MODULE_NAME} SHARED ${CMAKE_SOURCE_DIR}/builttime.c #要生成一个so,至少要包含一个源文件,实在没有可以把库的编译时间戳打到这儿。 ) target_link_libraries( ${MODULE_NAME} ${${MODULE_NAME}_EXTRA_LDFLAGS} "-Wl,--whole-archive" #告诉编译器,
从这里开始,所有的库的内容都包含到so中 ${LOCAL_MODULES} #可以是以源代码生成的静态库 ${PREBUILT_MODULES} #可以是预先生成的静态库 "-Wl,--no-whole-archive" #告诉编译器,从这里开始,以后的库的内容不用都包含到so中 )
㈢ cmake 怎么样编译库的时候加其他库
编译mac静态库
这个比较简单,直接Xcode -GXcode,然后用xcodebuild命令即可。
编译Andoird静态库
编译android库我们同样可以引入一个toolchain文件,这里我是从 android-cmake 里面下载的。
在使用这个toolchain文件之前,我们先要使用ndk自带的make-standalone-toolchain.sh脚本来生成对应平台的toolchain.这个脚本位于你的NDK的路径下面的buil/tools目录下。
比如要生成arm平台的toolchain,我们可以使用下列命令:
sh $ ANDROID_NDK / build / tools / make - standalone - toolchain . sh -- platform = android - $ANDROID_API_LEVEL -- install - dir = . / android - toolchain -- system = darwin - x86_64 -- ndk - dir = /Users / guanghui / AndroidDev / android - ndk - r9d / -- toolchain = arm - linux - androideabi - 4.8
这里的$ANDROID_NDK为你的NDK的安装路径。这段命令可以生成arm的toolchain,最终可以编译出armeabi和armeabi-v7a静态库。 如果想生成x86的toolchain,指需要使用下列命令:
sh $ ANDROID_NDK / build / tools / make - standalone - toolchain . sh -- platform = android - $ANDROID_API_LEVEL -- install - dir = . / android - toolchain - x86 -- system = darwin - x86_64 -- ndk - dir= / Users / guanghui / AndroidDev / android - ndk - r9d / -- toolchain = x86 - 4.8
最后,我们要告诉CMake使用外部toolchain文件,可以使用参数-DCMAKE_TOOLCHAIN_FILE=xxx。此外,我们还需要在导出两个环境变量给此toolchain文件:
export PATH = $ PATH : . / android - toolchain / bin
export ANDROID_STANDALONE_TOOLCHAIN = . / android - toolchain
cmake - DCMAKE_TOOLCHAIN_FILE = . . / android . toolchain . cmake - DANDROID_ABI = "armeabi" . .
㈣ 怎么用CMake编译freeglut
1、解开freeglut-3.0.0的压缩包,用记事本打开目录树下的“README.cmake”文件,下载Binary distributions。
2、下载好,解开其压缩包后,找到可执行文件,cmake-3.2.2-win32-x86/bin/cmake-gui.exe,运行之,
3、在两个where后边填上目录树的路径(注意不是src的路径,本文以R:/freeglut-3.0.0为例),点击configure按钮,弹出如下的对话框,从中选择所需的开发环境:
4、这里支持的环境好多,选择需要的环境,然后点击Finish,它会开始检查这个环境,然后给出一些配置选项:
5、从中修改静态库目标的安装位置(本例安装在R:/freeglut_static),勾掉不需要的选项(比如Demo、动态连接库等),点击Generate,即可生成工程。
6、打开工程后,找到工程设置,在此可以按照自己的需要修改一些配置,实际上绝大多数都不必动,有可能需要修改的也就是这么个地方:
7、这个按照自己的需要选择单线程运行库或是多线程运行库,或是多线程的DLL版运行库,主要是为了防止和别的库或者别的工程的设置冲突。
然后批量编译:
8、勾掉不必要的选项,比如MinSizeRel是在Release版本的基础上,改成最小尺寸优化的版本;RelWithDebInfo是在Release版本的基础上,添加调试信息的版本。这俩版本的可以不要。然后,点击Rebuild All,编译完就可以在安装目录下找到最终文件了。
㈤ 关于c/c++静态库和动态库的区别
静态库
之所以成为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
试想一下,静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:
l 静态库对函数库的链接是放在编译时期完成的。
l 程序在运行时与函数库再无瓜葛,移植方便。
l 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。
下面编写一些简单的四则运算C++类,将其编译成静态库给他人用,头文件如下所示:
StaticMath.h头文件
#pragma once
class StaticMath
{
public:
StaticMath(void);
~StaticMath(void);
static double add(double a, double b);//加法
static double sub(double a, double b);//减法
static double mul(double a, double b);//乘法
static double div(double a, double b);//除法
void print();
};
Linux下使用ar工具、Windows下vs使用lib.exe,将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和检索。一般创建静态库的步骤如图所示:
图:创建静态库过程
Linux下创建与使用静态库
Linux静态库命名规则
Linux静态库命名规范,必须是"lib[your_library_name].a":lib为前缀,中间是静态库名,扩展名为.a。
创建静态库(.a)
通过上面的流程可以知道,Linux创建静态库过程如下:
l 首先,将代码文件编译成目标文件.o(StaticMath.o)
g++ -c StaticMath.cpp
注意带参数-c,否则直接编译为可执行文件
l 然后,通过ar工具将目标文件打包成.a静态库文件
ar -crv libstaticmath.a StaticMath.o
生成静态库libstaticmath.a。
大一点的项目会编写makefile文件(CMake等等工程管理工具)来生成静态库,输入多个命令太麻烦了。
使用静态库
编写使用上面创建的静态库的测试代码:
测试代码:
#include "StaticMath.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
double a = 10;
double b = 2;
cout << "a + b = " << StaticMath::add(a,
b) << endl;
cout << "a - b = " << StaticMath::sub(a,
b) << endl;
cout << "a * b = " << StaticMath::mul(a,
b) << endl;
cout << "a / b = " << StaticMath::div(a,
b) << endl;
StaticMath sm;
sm.print();
system("pause");
return 0;
}
Linux下使用静态库,只需要在编译的时候,指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,-l选项)。
# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath
l -L:表示要连接的库所在目录
l -l:指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库的名称。
Windows下创建与使用静态库
创建静态库(.lib)
如果是使用VS命令行生成静态库,也是分两个步骤来生成程序:
l 首先,通过使用带编译器选项 /c 的 Cl.exe 编译代码 (cl
/c StaticMath.cpp),创建名为“StaticMath.obj”的目标文件。
l 然后,使用库管理器 Lib.exe 链接代码 (lib StaticMath.obj),创建静态库StaticMath.lib。
当然,我们一般不这么用,使用VS工程设置更方便。创建win32控制台程序时,勾选静态库类型;打开工程“属性面板”è”配置属性”è”常规”,配置类型选择静态库。
图:vs静态库项目属性设置
Build项目即可生成静态库。
使用静态库
测试代码Linux下面的一样。有3种使用方法:
方法一:
在VS中使用静态库方法:
l 工程“属性面板”è“通用属性”è “框架和引用”è”添加引用”,将显示“添加引用”对话框。 “项目”选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。 在“项目”选项卡中,选择 StaticLibrary。 单击“确定”。
l 添加StaticMath.h 头文件目录,必须修改包含目录路径。打开工程“属性面板”è”配置属性”è “C/C++”è” 常规”,在“附加包含目录”属性值中,键入StaticMath.h 头文件所在目录的路径或浏览至该目录。
编译运行OK。
图:静态库测试结果(vs)
如果引用的静态库不是在同一解决方案下的子工程,而是使用第三方提供的静态库lib和头文件,上面的方法设置不了。还有2中方法设置都可行。
方法二:
打开工程“属性面板”è”配置属性”è “链接器”è”命令行”,输入静态库的完整路径即可。
方法三:
l “属性面板”è”配置属性”è “链接器”è”常规”,附加依赖库目录中输入,静态库所在目录;
l “属性面板”è”配置属性”è “链接器”è”输入”,附加依赖库中输入静态库名StaticLibrary.lib。
动态库
通过上面的介绍发现静态库,容易使用和理解,也达到了代码复用的目的,那为什么还需要动态库呢?
为什么还需要动态库?
为什么需要动态库,其实也是静态库的特点导致。
l 空间浪费是静态库的一个问题。
l 另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
动态库特点总结:
l 动态库把对一些库函数的链接载入推迟到程序运行的时期。
l 可以实现进程之间的资源共享。(因此动态库也称为共享库)
l 将一些程序升级变得简单。
l 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。
Window与Linux执行文件格式不同,在创建动态库的时候有一些差异。
l 在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。
l Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。
与创建静态库不同的是,不需要打包工具(ar、lib.exe),直接使用编译器即可创建动态库。
Linux下创建与使用动态库
linux动态库的命名规则
动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为“.so”。
l 针对于实际库文件,每个共享库都有个特殊的名字“soname”。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。
l 在文件系统中,soname仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件(lib+soname+.so)。
创建动态库(.so)
编写四则运算动态库代码:
DynamicMath.h头文件
#pragma once
class DynamicMath
{
public:
DynamicMath(void);
~DynamicMath(void);
static double add(double a, double b);//¼Ó·¨
static double sub(double a, double b);//¼õ·¨
static double mul(double a, double b);//³Ë·¨
static double div(double a, double b);//³ý·¨
void print();
};
l 首先,生成目标文件,此时要加编译器选项-fpic
g++ -fPIC -c DynamicMath.cpp
-fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
l 然后,生成动态库,此时要加链接器选项-shared
g++ -shared -o libdynmath.so DynamicMath.o
-shared指定生成动态链接库。
其实上面两个步骤可以合并为一个命令:
g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp
使用动态库
编写使用动态库的测试代码:
测试代码:
#include "../DynamicLibrary/DynamicMath.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
double a = 10;
double b = 2;
cout << "a + b = " << DynamicMath::add(a, b) << endl;
cout << "a - b = " << DynamicMath::sub(a, b) << endl;
cout << "a * b = " << DynamicMath::mul(a, b) << endl;
cout << "a / b = " << DynamicMath::div(a, b) << endl;
DynamicMath dyn;
dyn.print();
return 0;
}
引用动态库编译成可执行文件(跟静态库方式一样):
g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath
然后运行:./a.out,发现竟然报错了!!!
可能大家会猜测,是因为动态库跟测试程序不是一个目录,那我们验证下是否如此:
发现还是报错!!!那么,在执行的时候是如何定位共享库文件的呢?
1) 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)。
2) 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。
如何让系统能够找到它:
l 如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
l 如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:
n 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
n 运行ldconfig ,该命令会重建/etc/ld.so.cache文件
我们将创建的动态库复制到/usr/lib下面,然后运行测试程序。
Windows下创建与使用动态库
创建动态库(.dll)
与Linux相比,在Windows系统下创建动态库要稍微麻烦一些。首先,需要一个DllMain函数做出初始化的入口(创建win32控制台程序时,勾选DLL类型会自动生成这个文件):
dllmain.cpp入口文件
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hMole,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
通常在导出函数的声明时需要有_declspec(dllexport)关键字:
DynamicMath.h头文件
#pragma once
class DynamicMath
{
public:
__declspec(dllexport) DynamicMath(void);
__declspec(dllexport) ~DynamicMath(void);
static __declspec(dllexport) double add(double a, double b);//加法
static __declspec(dllexport) double sub(double a, double b);//减法
static __declspec(dllexport) double mul(double a, double b);//乘法
static __declspec(dllexport) double div(double a, double b);//除法
__declspec(dllexport) void print();
};
生成动态库需要设置工程属性,打开工程“属性面板”è”配置属性”è”常规”,配置类型选择动态库。
图:v动态库项目属性设置
Build项目即可生成动态库。
使用动态库
创建win32控制台测试程序:
TestDynamicLibrary.cpp测试程序
#include "stdafx.h"
#include "DynamicMath.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
double a = 10;
double b = 2;
cout << "a + b = " << DynamicMath::add(a,
b) << endl;
cout << "a - b = " << DynamicMath::sub(a,
b) << endl;
cout << "a * b = " << DynamicMath::mul(a,
b) << endl;
cout << "a / b = " << DynamicMath::div(a,
b) << endl;
DynamicMath dyn;
dyn.print();
system("pause");
return 0;
}
方法一:
l 工程“属性面板”è“通用属性”è “框架和引用”è”添加引用”,将显示“添加引用”对话框。“项目”选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。 在“项目”选项卡中,选择 DynamicLibrary。 单击“确定”。
l 添加DynamicMath.h 头文件目录,必须修改包含目录路径。打开工程“属性面板”è”配置属性”è “C/C++”è” 常规”,在“附加包含目录”属性值中,键入DynamicMath.h 头文件所在目录的路径或浏览至该目录。
编译运行OK。
图:动态库测试结果(vs)
方法二:
l “属性面板”è”配置属性”è “链接器”è”常规”,附加依赖库目录中输入,动态库所在目录;
l “属性面板”è”配置属性”è “链接器”è”输入”,附加依赖库中输入动态库编译出来的DynamicLibrary.lib。
这里可能大家有个疑问,动态库怎么还有一个DynamicLibrary.lib文件?即无论是静态链接库还是动态链接库,最后都有lib文件,那么两者区别是什么呢?其实,两个是完全不一样的东西。
StaticLibrary.lib的大小为190KB,DynamicLibrary.lib的大小为3KB,静态库对应的lib文件叫静态库,动态库对应的lib文件叫【导入库】。实际上静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
动态库的显式调用
上面介绍的动态库使用方法和静态库类似属于隐式调用,编译的时候指定相应的库和查找路径。其实,动态库还可以显式调用。【在C语言中】,显示调用一个动态库轻而易举!
在Linux下显式调用动态库
#include <dlfcn.h>,提供了下面几个接口:
l void * dlopen( const char * pathname, int mode ):函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。
l void* dlsym(void* handle,const char* symbol):dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。
l int dlclose (void *handle):dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
l const char *dlerror(void):当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
在Windows下显式调用动态库
应用程序必须进行函数调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:
l 调用 LoadLibrary(或相似的函数)以加载 DLL 和获取模块句柄。
l 调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引用,故无需与导入库链接。
l 使用完 DLL 后调用 FreeLibrary。
显式调用C++动态库注意点
对C++来说,情况稍微复杂。显式加载一个C++动态库的困难一部分是因为C++的name
mangling;另一部分是因为没有提供一个合适的API来装载类,在C++中,您可能要用到库中的一个类,而这需要创建该类的一个实例,这不容易做到。
name mangling可以通过extern "C"解决。C++有个特定的关键字用来声明采用C
binding的函数:extern "C" 。用 extern "C"声明的函数将使用函数名作符号名,就像C函数一样。因此,只有非成员函数才能被声明为extern
"C",并且不能被重载。尽管限制多多,extern "C"函数还是非常有用,因为它们可以象C函数一样被dlopen动态加载。冠以extern
"C"限定符后,并不意味着函数中无法使用C++代码了,相反,它仍然是一个完全的C++函数,可以使用任何C++特性和各种类型的参数。
㈥ cmake编译SimpleAmqpClientCould的时候 NOT find Boost (missing: chrono system)报错,要怎么解决呢
看看你的D:/AMQP/SimpleAmqpClient/build/CMakeFiles/CmakeOutput.log写着什么错误
还有你每一步都要用管理员模式运行,CMake也好,VS也好,只要是打开工具,都用管理员模式
另外确保你的boost的路径没错,虽然我完全没用过你这些库,但是你的BOOST_ROOT和BOOST_INCLUDE_DIR一样,我有一点点怀疑会不会设置错了
也有可能FindBoost.cmake有问题,网上有人用Cmake需要要到Boost时,也碰到过由于这个make里面需要的boost文件名字和编译出来的不一样,导致出错
也有可能需要的是Boost的静态库,需要你点CMake的那个Advanced,可以找到
这个链接你参考一下
网页链接
㈦ 如何使用cmake生成基于静态库的动态链接库
在工程搭建时,可能会有将静态库链接成动态库的需求,如出于代码保护的角度,某些模块会发布.a扩展名的静态库,我们要将多个这样的静态库链接成一个动态
库。但与直接link目标文件不同的是,ld以默认参数执行时,并把静态库中没有用到的函数过滤掉,导致生成的so并未包含所要的函数,因此要加上
--whole-archive参数,以保证所有的函数都包含在生成的so中。
在使用cmake时,CMakeLists.txt的写法如下:
add_library(
${MODULE_NAME}
SHARED
${CMAKE_SOURCE_DIR}/builttime.c #要生成一个so,至少要包含一个源文件,实在没有可以把库的编译时间戳打到这儿。
)
target_link_libraries(
${MODULE_NAME}
${${MODULE_NAME}_EXTRA_LDFLAGS}
"-Wl,--whole-archive" #告诉编译器,从这里开始,所有的库的内容都包含到so中
${LOCAL_MODULES} #可以是以源代码生成的静态库
${PREBUILT_MODULES} #可以是预先生成的静态库
"-Wl,--no-whole-archive" #告诉编译器,从这里开始,以后的库的内容不用都包含到so中
)