在上一篇文章的最后,对于外部库的依赖,我直接使用了gcc进行编译。因为示例非常简单的缘故,所以使用这种方式没毛病。试想一下,如果是一个综合性的工程,显然这种方式就显得不合适了。当然除了cmake外还有其他的编译构建工具,由于本系列文章的主角儿是cmake,所以本文使用cmake来展示外部库的导入编译。
目录结构
.
|-- build
|-- CMakeLists.txt
|-- inc
| `-- add.h
|-- lib # 动态库所在目录
|-- out # 静态库所在目录
`-- src
`-- main.c
mian.c
#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int main(int argc, char** argv)
{
int a = 1;
int b = 2;
printf("%d+%d=%d\n", a, b, add(a,b));
return 0;
}
CMakeLists.txt
方法一
本方法主要使用link_directories()和target_link_libraries()命令来完成对动态库或静态库的编译。
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
cmake_policy(SET CMP0048 NEW)
project(test05 VERSION "1.0.0.0")
include_directories(${PROJECT_SOURCE_DIR}/inc)
aux_source_directory(${PROJECT_SOURCE_DIR}/src src_dirs)
#link_directories(${PROJECT_SOURCE_DIR}/lib) # 指定动态库搜索路径,类似于LD_LIBRARY_PATH
link_directories(${PROJECT_SOURCE_DIR}/out) # 指定静态库搜索路径
add_executable(test_add ${src_dirs})
# target_link_libraries(test_add add) # 链接动态库
target_link_libraries(test_add libadd_static.a) # 链接静态库
第9行和第14行是编译动态库;第10行和第15行是编译静态库;
link_directories()
link_directories([AFTER|BEFORE] directory1 [directory2 ...])
指定库的搜索路径。AFTER
和BEFORE
的作用与include_directories()的作用相同,分别表示"尾插"和"头插"。
一般directoryx
给绝对路径。
target_link_libraries()
target_link_libraries(<target> ... <item>... ...)
指定库名。<target> 表示add_executable()或add_library()的target,例如,本例中,target为’test_add’。所以一般target_link_libraries()在add_executable()或add_library()之后,原因是要先有target。
<item> 表示库名(A library target name),例如,本例中,item为"add"或"libadd_static.a"。也可以是库的全路径(A full path to a library file)。
方法二
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
cmake_policy(SET CMP0048 NEW)
project(test05 VERSION "1.0.0.0")
include_directories(${PROJECT_SOURCE_DIR}/inc)
aux_source_directory(${PROJECT_SOURCE_DIR}/src src_dirs)
#find_library(dy_lib add ${PROJECT_SOURCE_DIR}/lib)
#find_library(dy_lib libadd.so ${PROJECT_SOURCE_DIR}/lib)
find_library(dy_lib libadd_static.a ${PROJECT_SOURCE_DIR}/out)
add_executable(test_add ${src_dirs})
target_link_libraries(test_add ${dy_lib}) # 链接外部库
find_library()
find_library (<VAR> name1 [path1 path2 ...])
在指定路径下查找指定的库,并将查找到的库的路径存储在<VAR>中。例如,本例中,将’${PROJECT_SOURCE_DIR}/out/libadd_static.a’存储在变量’dy_lib’中。
编译
cd build
cmake ..
make
编译后的目录结构:
|-- build
| |-- CMakeCache.txt
| |-- CMakeFiles
| |-- cmake_install.cmake
| |-- Makefile
| `-- test_add
|-- CMakeLists.txt
|-- inc
| `-- add.h
|-- lib
| `-- libadd.so
|-- out
| `-- libadd_static.a
|-- src
| `-- main.c
执行 ./test_add,打印输出"1+2=3"。
cmake-动态库和静态库的编译和本文两篇文章的例子中,都是将库分开处理的。假设有这样一个需求,一个大型工程的编译中,不仅要有可执行程序生成,而且还有动态库的生成,或者说构建一个sdk。显然就会涉及子模块的编译问题,接下来我们将要解决这个问题。