cmake基础(2)——动/静态库

一、静态库创建

1. 准备

首先创建目录和文件结构如下:

文件内容如下:

class Hello
{
public:
	void print();
};
#include "hello.h"
#include <iostream>

void Hello::print() {
	std::cout << "hello world!" << std::endl;
}
project(hello_static)
file(GLOB SOURCES "src/*.*")

add_library(${PROJECT_NAME} STATIC ${SOURCES})

2. 构建&编译

首先在CMakeLists.txt同目录下打开命令行工具,通过

cmake -S . -B build

命令生成项目信息。

然后通过

cmake --build build

命令执行构建。

执行完成后可以看到在build/Debug目录下生成静态库hello_static.lib文件。

3. 说明

1.首先这里通过project命令声明项目名为hello_static,然后通过file(GLOB )命令设置源文件到SOURCES变量中,这两者在上一节已经描述过。

2.最后使用add_library()命令生成库。

add_library()命令原型如下:

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [source1] [source2 ...])
  • 参数<name>为逻辑目标名称,项目内唯一。实际产物名基于平台而变化(lib<name>.so或者<name>.lib)
  • STATIC | SHARED | MODULE。表示库类型,分别表示静态,动态和插件库()。默认值与变量BUILD_SHARED_LIBS是否开启有关(开启为动态否则为静态)。
  • EXCLUDE_FROM_ALL。表示EXCLUDE_FROM_ALL属性,默认true,此属性表示将当前目标排除在外,即如果设置了此参数,则在其当前项目以及父类以上的项目使用类似于make之类的操作都不响应(试了vs的生成是响应的。)。使用方式为add_library(<name> [STATIC | SHARED | MODULE] EXCLUDE_FROM_ALL [source1] [source2 ...])
  • 最后是源码列表。

此处只用到了其中的三个参数。

  • ${PROJECT_NAME}。表示使用PROJECT_NAME变量值。
  • STATIC。表示为一个静态库
  • ${SOURCES}。表示使用file创建的源文件集合变量。

二、动态库创建

1.准备

准备与静态库相同的目录结构与文件内容。

并修改CMakeLists.txt为:

project(hello_shared)
file(GLOB SOURCES "src/*.*")

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(${PROJECT_NAME} SHARED ${SOURCES})

2.构建&编译

与静态库相同。区别是产物为hello_shared.dll和hello_shared.lib.

3.说明

首先这里开启了CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS变量,保证能够生成lib文件,方便下一节链接使用。

实际上在windows下,如果没有导出任何内容(而linux下默认导出),则生成的动态库产物不包含lib文件,也就无法使用。(这里也可以通过添加导出的方式触发生成lib文件)

三、使用动/静态库

因为动/静态库的使用方式类似,所以这里使用同一个例子演示。

1.准备

首先创建如下目录:

其中hello.h,hello_shared.lib,hello_static.lib,hello_shared.dll则是前面编译的动/静态库产物。然后CMakeLists.txt和main.cpp内容如下:

project(static_use)
file(GLOB SOURCES "src/*.*")

add_executable(${PROJECT_NAME} ${SOURCES})

target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/externals/include)
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/externals/lib/hello_shared.lib)
#target_link_libraries(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/externals/lib/hello_static.lib)
#include "hello.h"

int main()
{
    Hello hello;
    hello.print();
    return 0;
}

2.构建&编译

与之前一样通过cmake -S . -B build和cmake --build build命令进行构建和编译。

可以看到build/Debug目录下生成static_use.exe产物。

3.说明

首先,当前生效的内容为动态库,最后一句注释为静态库调用方式,将第7行替换则表示调用静态库。

前三句命令之前都有讲到,这里不再赘述。

链接动/静态库主要有两个命令:

  • target_include_directories
  • target_link_libraries

3.1 target_include_directories

完整语法为:

target_include_directories(<target> [SYSTEM] [BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

添加头文件目录。可以用在链接三方库,也可以用在项目内。最直观的表现为使用#include的时候,相对路径起始位置为items1,items2...

比如对于如下目录结构:

如果没有使用target_include_directories命令指定,则在引用hello.h头文件时,需要:

#include "inc/hello.h"

而添加了

target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/src/inc)

命令后,则可以变为

#include "hello.h"
命令说明:
  • <target>为目标名,且不能是别名
  • BEFORE。表示将目录追加还是前置到已有目录
  • INTERFACE|PUBLIC|PRIVATE。表示指定目录的作用域,PRIVATE和PUBLIC项将填充<target>的INCLUDE_DIRECTORIES属性。PUBLIC和INTERFACE项将填充<target>的INTERFACE_INCLUDE_DIRECTORIES属性。

3.2 target_link_libraries

此命令比较复杂,这里只介绍本案例使用的场景(A full path to a library file)。

完整语法为:

target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

指定链接的库或者依赖文件。这里使用的item为库的完成路径。

  • <target>为目标名,且不能是别名
  • INTERFACE|PUBLIC|PRIVATE。PUBLIC表示会链接到库,并成为接口的一部分(可以被外部使用)。PRIVATE则表示链接到库,但不作为接口(不能被外部引用)。INTERFACE表示链接到接口,但是不链接到库。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值