【CMake】(7)生成库

静态库生成

假设你的项目结构如下:

MyProject/
├── CMakeLists.txt
├── include/
│   └── head.h
└── src/
    ├── add.cpp
    ├── div.cpp
    ├── mult.cpp
    └── sub.cpp

你想要将src目录下的源文件编译成一个名为calc的静态库,并将该库的头文件放在include目录下。

#ifndef _HEAD_H_
#define _HEAD_H_
// 加法
int add(int a, int b);
// 减法
int subtract(int a, int b);
// 乘法
int multiply(int a, int b);
// 除法
double divide(int a, int b);

#endif // _HEAD_H_

CMakeLists.txt文件配置

为了生成静态库,你需要在CMakeLists.txt文件中指定库的名称、类型(静态或动态),以及包含在库中的源文件。

cmake_minimum_required(VERSION 3.0)
project(CALC)

# 包含头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 搜索当前目录下的所有源文件,并将名称保存到 SRC_LIST 变量
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

# 添加静态库目标
add_library(calc STATIC ${SRC_LIST})

这里的add_library命令用于生成静态库。calc是库的名称,STATIC指明这是一个静态库,${SRC_LIST}包含了要编译进库的所有源文件。

静态库命名约定

  • Linux上,静态库的命名约定是lib前缀加上库的名称,然后是.a后缀。例如,上述示例中的库将会被命名为libcalc.a
  • Windows上,静态库通常有.lib后缀,但没有lib前缀,因此上述库可能会被命名为calc.lib

使用静态库

一旦静态库被创建,它就可以被其他项目通过target_link_libraries命令链接使用了。如果静态库和主项目在同一个CMake项目中,可以直接链接;如果不在,可能需要使用find_library或者手动设置静态库的路径。

vs使用方法
1. 将静态库添加到项目中

首先,你需要将静态库文件(.lib)复制到你的项目目录中,或者至少保证Visual Studio能够找到它。
![[1707799640675.jpg]]

2. 配置项目以链接静态库

接下来,需要配置项目来链接这个静态库。方法如下:

  • 打开Visual Studio,右键点击解决方案资源管理器中的项目名,选择"属性"。
  • 点击“C/C++“->“常规“,在“附加包含目录"字段添加头文件的地址。
    ![[Pasted image 20240213125305.png]]
  • 在弹出的属性页中,选择“链接器”->“输入”,在“附加依赖项”字段中输入你的静态库文件名,比如calc.lib。如果有多个库,用分号隔开。
    ![[Pasted image 20240213125356.png]]
  • 如果你的静态库不在项目目录中,还需要在“链接器”->“常规”下的“附加库目录”中添加静态库所在的目录路径。
    ![[Pasted image 20240213125425.png]]
3. 包含头文件并调用
#include <stdio.h>
#include "head.h"
int main()
{
    int a = 20;
    int b = 12;
    printf("a = %d, b = %d\n", a, b);
    printf("a + b = %d\n", add(a, b));
    printf("a - b = %d\n", subtract(a, b));
    printf("a * b = %d\n", multiply(a, b));
    printf("a / b = %f\n", divide(a, b));
    return 0;
}

注意

  • 确保在Release和Debug模式下都配置了静态库,有时你可能需要为不同的编译模式链接不同版本的库。
  • 如果在链接时出现找不到符号的错误,可能是因为没有正确配置静态库,或者静态库和你的项目使用了不同的运行时库设置(比如,一个使用了多线程DLL,另一个没有)。确保库和你的项目使用了相同的设置。

动态库生成

动态库在程序运行时被加载,可以被多个程序共享,这样可以节省内存,同时也便于更新和维护。

步骤 1: 准备源代码

首先,你需要有源代码文件。假设你的项目结构如下所示,其中包括多个.c文件(或.c)和头文件:

MyProject/
├── include/
│   └── head.h
└── src/
    ├── add.c
    ├── div.c
    ├── mult.c
    └── sub.c

head.h文件可能看起来像这样:

#ifndef _HEAD_H_
#define _HEAD_H_

#ifdef _WIN32
#ifdef CALC_EXPORTING
#define CALC_API __declspec(dllexport)
#else
#define CALC_API __declspec(dllimport)
#endif
#else
#define CALC_API
#endif

#ifdef __cplusplus
extern "C" {
#endif

// 加法
CALC_API int add(int a, int b);
// 减法
CALC_API int subtract(int a, int b);
// 乘法
CALC_API int multiply(int a, int b);
// 除法
CALC_API double divide(int a, int b);
  
#ifdef __cplusplus
}
#endif

#endif // _HEAD_H_

步骤 2: 编写CMake配置

在项目的根目录下创建一个CMakeLists.txt文件,并填写以下内容:

cmake_minimum_required(VERSION 3.0)

project(CALC)

# 设置C++标准
set(CMAKE_CXX_STANDARD 11)

# 设置可执行文件的输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/)

# 添加头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)

# 查找当前目录下的所有源文件,并将名称保存到 SRC_LIST 变量
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
# 添加一个可执行文件
#add_executable(app  ${SRC_LIST})
# 添加静态库目标
add_library(calc SHARED ${SRC_LIST})

target_compile_definitions(calc PRIVATE CALC_EXPORTING)

步骤 3: 构建动态库

在项目根目录下,打开终端或命令提示符,运行以下命令来创建构建目录(如果还没有)并使用CMake配置项目:

mkdir build
cmake -S . -B build
cmake --build build

这会在指定的库输出路径(这里是项目根目录下的lib文件夹)生成动态库文件libcalc.so(在Linux上)或calc.dll(在Windows上)和对应平台的静态库文件,这两个文件都是需要的。

  • 动态库的名字和格式取决于你的操作系统。在Linux和UNIX系统上,动态库通常有.so扩展名,在Windows上则是.dll
  • 使用动态库时,确保在运行时库路径可找到,否则程序可能无法启动。在Linux上,你可以使用LD_LIBRARY_PATH环境变量来指定动态库的搜索路径。
  • 动态库的一个优点是可以在不重新编译程序的情况下更新库。然而,要确保新版本的库是向后兼容的,以避免运行时错误。

使用动态库

vs使用方法

同静态库基本一致,lib和dll文件都需要,而且注意默认情况下要将dll文件放置到项目根目录。

输出路径

可以通过设置特定的变量来指定库文件(无论是动态库还是静态库)和可执行文件的输出路径。

方式1 - 主要适用于动态库和可执行文件

通过设置EXECUTABLE_OUTPUT_PATH变量,你可以指定可执行文件和具有执行权限的动态库文件的输出路径。这种方式主要适用于动态库和可执行文件。

cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

# 设置动态库和可执行文件生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 生成动态库
add_library(calc SHARED ${SRC_LIST})
方式2 - 适用于动态库和静态库

使用LIBRARY_OUTPUT_PATH变量,可以同时指定动态库和静态库的输出路径。这个变量对于动态库和静态库都适用,但不影响可执行文件的输出路径。

cmake_minimum_required(VERSION 3.0)
project(CALC)
include_directories(${PROJECT_SOURCE_DIR}/include)
file(GLOB SRC_LIST "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

# 设置动态库/静态库生成路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

# 生成动态库
# add_library(calc SHARED ${SRC_LIST})
# 生成静态库
add_library(calc STATIC ${SRC_LIST})

注意事项

  • EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH 变量指定的是目标文件生成时的路径,而不影响安装(make install)时的路径。安装路径需要通过INSTALL(TARGETS ...)命令单独指定。
  • 如果不指定输出路径,CMake默认会将目标文件放置在构建目录的某个子目录下,这个子目录的结构通常会反映源代码目录的结构。
  • 在多目标项目中,也可以对每个目标单独设置输出路径,通过为目标设置RUNTIME_OUTPUT_DIRECTORYLIBRARY_OUTPUT_DIRECTORYARCHIVE_OUTPUT_DIRECTORY属性实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

游码客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值