0x00 前言

文章中的文字可能存在语法错误以及标点错误,请谅解;

如果在文章中发现代码错误或其它问题请告知,感谢!

cmake version:3.10.2

0x01 add_library()生成普通库(Normal Libraries)语法

add_library()可以生成Normal Libraries、Object Libraries、Interface Libraries、Imported Libraries以及Alias Libraries。本文介绍add_library()生成Normal Libraries内容,语法如下:

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])

<name>表示库的名字,库最后的实际名字根据平台实际确定(lib< name >.a或< name >.lib),所以没必要将< name >中添加lib字样,平台会自动加上。

[STATIC | SHARED | MODULE]表示指定要创建库的类型,各类型含义如下:
STATIC:静态库,链接其他目标时使用。
SHARED:动态库,动态链接并在运行时加载。
MODULE:在使用dyld系统时有效,若不支持dyld则和SHARED一样。

[EXCLUDE_FORM_ALL]表示这个库不会被默认构建,除非有其他组件依赖或手动构建。

[<source>...]表示参与生成库包含的源文件。

0x02 使用举例

一般生成动态库遵循如下形式:

aux_source_directory(. LIBFUN_SRC) #查找该目录下的所有源文件,然后将结果存进指定变量名LIBFUN_SRC
ADD_LIBRARY(fun SHARED ${LIBFUN_SRC }) #生成动态库
ADD_LIBRARY(fun_static STATIC ${LIBFUN_SRC })#生成静态库

或者

SET(LIBFUN_SRC fun.c) #fun.c为源文件(可为多个) LIBFUN_SRC为变量名
ADD_LIBRARY(fun SHARED ${LIBFUN_SRC }) #生成动态库
ADD_LIBRARY(fun_static STATIC ${LIBFUN_SRC })#生成静态库

一个计算平方的项目代码结构如下(该项目完整代码地址:https://github.com/wzpan/cmake-demo/tree/master/Demo5。):

android studio cmake add_library文件夹 cmakelist add_library_cmake

其中math文件夹包含平方实现相关函数,该目录下CMakeLists.txt文件内容如下:

#查找当前目录下所有源文件
#并将名称保存到DIR_LIB_SRCS变量
aux_source_directory(. DIR_LIB_SRCS)

#生成链接库
add_library(MathFunctions ${DIR_LIB_SRCS})

#指定MathFunctions库安装路径
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

其中add_library(MathFunctions ${DIR_LIB_SRCS})中没有指定创建库类型,默认为STATIC

在根目录下执行cmake .生成makefile,然后使用make编译,进入到/math目录下查看生成了一个名为libMathFunctions.a的静态库:

android studio cmake add_library文件夹 cmakelist add_library_cmake_02

拓展
现在我们修改math目录下的CMakeLists.txt文件为以下内容,打算同时生成一个动态库libMathFunctions.so以及静态库libMathFunctions.a

#查找当前目录下所有源文件
#并将名称保存到DIR_LIB_SRCS变量
aux_source_directory(. DIR_LIB_SRCS)

#生成链接库
add_library(MathFunctions SHARED ${DIR_LIB_SRCS})
add_library(MathFunctions STATIC ${DIR_LIB_SRCS})

#指定MathFunctions库安装路径
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

此时使用cmake .生成makefile文件会报错,意味着我们不能将静态库.a以及动态库.so在CMakeLists.txt文件中使用add_library()命名为相同的名字——MathFunctions ,若我们将math目录下CMakeLists.txt文件中的add_library(MathFunctions STATIC ${DIR_LIB_SRCS})MathFunctions修改为MathFunctions_static即换一个名字后变成add_library(MathFunctions_static STATIC ${DIR_LIB_SRCS}),则cmake以及make通过,此时math目录如下:

android studio cmake add_library文件夹 cmakelist add_library_源文件_03

不过按照习惯,我们想要将动态库.so以及静态库.a命名一致,所以我们可以在add_library(MathFunctions_static STATIC ${DIR_LIB_SRCS})之后添加一行SET_TARGET_PROPERTIES (MathFunctions_static PROPERTIES OUTPUT_NAME "MathFunctions")

#查找当前目录下所有源文件
#并将名称保存到DIR_LIB_SRCS变量
aux_source_directory(. DIR_LIB_SRCS)

#生成链接库
add_library(MathFunctions SHARED ${DIR_LIB_SRCS})
add_library(MathFunctions_static STATIC ${DIR_LIB_SRCS})
SET_TARGET_PROPERTIES (MathFunctions_static PROPERTIES OUTPUT_NAME "MathFunctions")

#指定MathFunctions库安装路径
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

执行cmake .以及make之后math文件夹:

android studio cmake add_library文件夹 cmakelist add_library_cmake_04

可以看到该文件夹中可以同时存在MathFunctions .so以及MathFunctions .a两个同名库。

若要给动态库增加一个版本号,可以在SET_TARGET_PROPERTIES (MathFunctions_static PROPERTIES OUTPUT_NAME "MathFunctions")加入一行SET_TARGET_PROPERTIES (MathFunctions PROPERTIES VERSION 1.2 SOVERSION 1):

#查找当前目录下所有源文件
#并将名称保存到DIR_LIB_SRCS变量
aux_source_directory(. DIR_LIB_SRCS)

#生成链接库
add_library(MathFunctions SHARED ${DIR_LIB_SRCS})
add_library(MathFunctions_static STATIC ${DIR_LIB_SRCS})
SET_TARGET_PROPERTIES (MathFunctions_static PROPERTIES OUTPUT_NAME "MathFunctions")

SET_TARGET_PROPERTIES (MathFunctions PROPERTIES VERSION 1.2 SOVERSION 1) 

#指定MathFunctions库安装路径
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

VERSION指代动态库版本,SOVERSION指代API版本。

执行cmake .以及make之后math文件夹:

android studio cmake add_library文件夹 cmakelist add_library_源文件_05

libMathFunctions.so.1.2为动态库文件名(realname),libMathFunctions.so.1为动态库别名(soname),libMathFunctions.so为动态库链接名。如果在make过程中出现以下问题,表明我们是在虚拟机VMware的共享文件夹中进行操作,可以将源码复制到linux本地目录,比如/home,删除已生成的cmake的相关文件,重新执行cmake .以及make

android studio cmake add_library文件夹 cmakelist add_library_cmake_06


以上。