由于cmake内容较多,篇幅较长,为了不让人疲倦,分成了多篇博客,全部博客链接如下
cmake简洁教程 - 第一篇_YZF_Kevin的博客-CSDN博客_cmake教程详解
cmake简洁教程 - 第二篇_YZF_Kevin的博客-CSDN博客
cmake简洁教程 - 第三篇_YZF_Kevin的博客-CSDN博客
cmake简洁教程 - 第四篇_YZF_Kevin的博客-CSDN博客
cmake简洁教程 - 第五篇_YZF_Kevin的博客-CSDN博客
本篇博客讲解如何使用cmake编译,链接动态库,静态库
第一小节:如何使用cmake编译动态库,静态库
举例,我们把下面源码编译出动态库和静态库,文件架构图如下(就是把cmake第三篇博客的文件重新挪了下位置,新添加了空目录lib用来存放最终编译出来的库文件)
其中CMakeLists.txt文件内容如下
cmake_minimum_required (VERSION 3.5)
project (demo)
set (SRC_LIST ${PROJECT_SOURCE_DIR}/func1/func1.c)
add_library (func1_shared SHARED ${SRC_LIST})
add_library (func1_static STATIC ${SRC_LIST})
set_target_properties (func1_shared PROPERTIES OUTPUT_NAME "func1")
set_target_properties (func1_static PROPERTIES OUTPUT_NAME "func1")
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
解释下
第4行:简单的set命令。变量 PROJECT_SOURCE_DIR 前篇博客已经讲过了,表工程根目录,也就是当前CMakeLists.txt文件所在目录。所以第4行的意思是把工程根目录下func1/func1.c文件设置到变量 SRC_LIST中
第6,7行:新命令,生成动态库或静态库,第一个参数表库的名字,第二个参数表动态库还是静态库,第三个参数表编译库所需的源文件
第9,10行:新命令,设置目标文件的属性,这里我们是设置了属性 OUTPUT_NAME 也就是最终的目标文件名字为func1,所以最终生成的动态库文件名为 libfunc1.so , 最终生成的静态库文件名为 libfunc1.a。注意该命令还可以设置目标文件的其他属性
第12行:仍然是普通的set命令,但使用了新的cmake全局变量,变量 LIBRARY_OUTPUT_PATH 表库文件的输出路径,这里我们设置在工程根目录下的lib文件夹下
注意:第9,10行可以没有,那么生成库文件的名字就是第6,7行的add_library命令的第一个参数。只是add_library命令有个缺点,就是连续两个 add_library命令的第一个参数不能一样。而 命令 set_target_properties就没有这样的限制,该命令指定的库名字可以一样,比如我们都指定叫func1,实际生成的文件一个是libfunc1.so,一个是libfunc1.a
好了,我们cd到build目录下,执行命令 cmake .. 意思是在当前目录执行cmake命令,但用的CMakeLists.txt文件在上层目录
再执行 make 命令,可以看到lib目录下已经产生了两个库文件
第二小节:如何使用cmake链接动态库,静态库
上一小节我们已经编译出了动态库(.so文件),静态库(.a文件),下面开始讲怎么使用这些动态库,静态库。
我们新建一个目录,把上面示例的.h头文件,编译的库文件都拷贝过来,文件架构图如下
其中main.c文件内容如下(也就是包含了库func1里面的头文件func.h后,调用了其函数func1)
#include <stdio.h>
#include "func1.h"
int main(void)
{
printf("Hello World\n");
func1();
return 0;
}
其中CMakeLists.txt文件内容如下
cmake_minimum_required (VERSION 3.5)
project (demo)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set (SRC_LIST ${PROJECT_SOURCE_DIR}/src/main.c)
include_directories (${PROJECT_SOURCE_DIR}/include)
find_library(FUNC1_LIB func1 HINTS ${PROJECT_SOURCE_DIR}/lib)
add_executable(main ${SRC_LIST})
target_link_libraries(main ${FUNC1_LIB})
解释下
第4行:简单的set命令,变量 EXECUTABLE_OUTPUT_PATH 用来设置最终输出的可执行文件的目录为工程根目录下的bin目录下
第5行:简单的set命令,变量 SRC_LIST 用来记录源文件列表
第7行:设置工程的头文件目录
第9行:新命令,在指定目录下查找指定库,并把库的绝对路径赋值给指定变量。第一个参数是变量名,第二个参数是库的名字,如果不写完整的库名字,则默认查找名字为libxxxx.so文件。第三个参数是HINTS,第四个参数是在哪个目录下查找
第11行:指定生成的可执行文件名,以及使用的源文件列表
第13行:新命令,把库文件和可执行程序进行链接,第一个参数是可执行程序名,第一个参数代表库
好了,我们cd到目录build下,依次执行命令 cmake .. make,再cd到bin目录下执行 ./main 可以看到执行成功了,如下图
注意:
之前cmake版本有使用命令 link_directories 来链接库的,但是某些情况下可能会有问题。
这里建议使用命令 find_library 来查找库,因为这样在执行cmake ..
时就会去查找库是否存在,可以提前发现错误,不用等到真正链接时才出错
目前官方也是建议放弃 link_directories,转而使用 find_library 或 find_package
本篇总结(2个新命令)
1. 命令 find_library() 在指定目录下查找指定库,并把库的绝对路径赋值给第一个参数
2. 命令 target_link_libraries 把库文件和可执行程序进行链接
至此,我们已经学习了基本的cmake用法,编译可执行程序,库文件,使用库文件
下一篇我们将会讲解更多扩展用法