文章目录

  • 1、语法
  • 2、实践
  • 2.1 编写代码
  • 2.2 编译
  • 3、总结


有时我们只需要编译出动态库,静态库,然后等着让其它程序去使用。这种情况下我们需要使用add_library函数。

1、语法

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

<name>

  • 表示库文件的名字,该库文件会根据命令里列出的源文件来创建。
  • < name>对应于逻辑目标名称,并且在项目中必须是全局唯一的。
  • 构建的库的实际文件名是基于本机平台的约定(如lib< name>.a或< name>.lib)构建的。

[STATIC | SHARED | MODULE]

指定要创建的库的类型

  • SHARED:
  • 动态库。动态库是动态链接并在运行时加载的
  • 如果库不导出任何符号,则不能将其声明为SHARED库
  • STATIC:静态库。静态库是在链接其他目标时使用的目标文件存档
  • MODULE:
  • 模块库是没有链接到其他目标的插件,但可以在运行时使用类似dlopen的功能动态加载
  • 在使用 dl 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。

EXCLUDE_FROM_ALL:这个库不会被默认构建(排除到默认目标all之外),除非有其他的组件依赖或者手工构建。

[source1] [source2] [...]:指定生成库的源文件

当我们使用CMake构建项目时,可以通过设置BUILD_SHARED_LIBS变量来决定是否构建共享库(SHARED)或静态库(STATIC)。如果BUILD_SHARED_LIBS变量的值为ON,则构建的库类型为SHARED;如果为OFF,则构建的库类型为STATIC。

另外,在构建SHARED和MODULE库时,CMake会自动设置POSITION_INDEPENDENT_CODE目标属性为ON。这个属性表示生成的库是否包含了位置无关代码(Position Independent Code),这对于共享库和动态链接库是必要的。位置无关代码的特点是可以在内存中的任意位置加载和执行,这使得共享库能够在不同的进程地址空间中重用。

2、实践

2.1 编写代码

项目结构如下:

android cmake 设置so生成位置 cmake生成lib_cmake

/*
** testFunc.c
*/

#include <stdio.h>
#include "testFunc.h"

void func(int data)
{
	printf("data is %d\n", data);
}

/*
** testFunc.h
*/

#ifndef _TEST_FUNC_H_
#define _TEST_FUNC_H_

void func(int data);

#endif

最外层的CMakeLists.txt内容如下:

cmake_minimum_required (VERSION 2.8)

project (demo)

#向当前工程添加存放源文件的子目录
add_subdirectory (lib_testFunc)

lib_testFunc目录下的CMakeLists.txt如下:

aux_source_directory (. SRC_LIST)

# 使用${SRC_LIST}为原材料生成一个叫做testFunc_shared 的动态库
add_library (testFunc_shared SHARED ${SRC_LIST})
# 使用${SRC_LIST}为原材料生成一个叫做testFunc_static 的静态库
add_library (testFunc_static STATIC ${SRC_LIST})

# 将testFunc_shared 重新命名为 libtestFunc.so
set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")
# 将testFunc_static  重新命名为 libtestFunc.a
set_target_properties (testFunc_static PROPERTIES OUTPUT_NAME "testFunc")

# 设置 库文件的默认输出路径
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

命令:

  • add_library: 生成动态库或静态库(第1个参数指定库的名字;第2个参数决定是动态还是静态,如果没有就默认静态;第3个参数指定生成库的源文件)
  • set_target_properties: 设置输出的名称,还有其它功能,如设置库的版本号等等。

预定义变量:

  • LIBRARY_OUTPUT_PATH: 库文件的默认输出路径,这里设置为工程目录下的lib目录

2.2 编译

现在,让我们进入build目录下运行cmake …,成功后再运行make:

android cmake 设置so生成位置 cmake生成lib_静态库_02

cd到lib目录下进行查看,发现已经成功生成了动态库和静态库,

android cmake 设置so生成位置 cmake生成lib_c++_03

ps:可以看出前面使用set_target_properties重新定义了库的输出名字,如果不用set_target_properties也可以,那么库的名字就是add_library里定义的名字,只是我们连续2次使用add_library指定库名字时,这个名字不能相同,而set_target_properties可以把名字设置为相同,只是最终生成的库文件后缀不同,这样相对来说会好看点。

3、总结

命令总结:

命令

说明

示例

add_library

生成动态库或静态库

add_library (testFunc_shared SHARED ${SRC_LIST})

set_target_properties

设置目标属性

set_target_properties (testFunc_shared PROPERTIES OUTPUT_NAME "testFunc")

预定义变量总结:

预定义变量

说明

LIBRARY_OUTPUT_PATH

库文件的默认输出路径

库路径不设置的话,默认放在BINARY_DIR下,即构建时执行cmake命令的目录下。