CMake与静态库和动态库
如何生成静/动态库
静态库
在链接阶段会将汇编生成的目标文件
.o
与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。对函数库的链接是在编译时完成的!
静态库对空间的浪费是巨大的!
动态库
动态库不是在编译时被链接到目标代码中,而是运行时才被载入。
命名
动态库的命名
lib<name>.so/dll/dylib
静态库的命名
lib<name>.a/lib
动静态库的后缀名
- 在Windows系统中动静态库的后缀名分别为
dll
lib
- 在Linux系统中动静态库的后缀名分别为
so
a
- 在Mac系统中动静态库的后缀名分别为
dylib
a
命令
find()
:常用于搜索源文件add_library(<库名> STATIC ${SRC})
:生成静态库add_library(<库名> SHARED ${SRC})
:生成动态库${LIBRARY_OUTPUT_PATH}
:导出目录
直接测试
现在有以下目录结构及代码环境
cmake
# 配置CMake的最小版本
cmake_minimum_required(VERSION 3.20.0)
# 配置项目名称
project(test)
# 将src目录下的所有cpp文件添加到SRC变量中
file(GLOB SRC ${PROJECT_SOURCE_DIR}/src/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/include)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 生成静态库
add_library(animal_static STATIC ${SRC})
add_library(cat STATIC ${PROJECT_SOURCE_DIR}/src/cat.cpp)
# 在cmake中,同时生成静态库与动态库的时候,需要一些技巧;因为cmake中不能生成同名的静态库和动态库,只能先生成不同名的库之后再把其中一个库的名字改名。
# set_target_properties(animal_static PROPERTIES OUTPUT_NAME "animal")
# 生成动态库
add_library(animal SHARED ${SRC})
add_library(dog SHARED ${PROJECT_SOURCE_DIR}/src/dog.cpp)
cpp
#pragma once
#include <string>
class Cat {
private:
std::string name_;
std::string bark_;
public:
Cat(std::string name, std::string bark = "Miao~ miao~");
void bark();
};
cpp
#pragma once
#include <string>
class Dog {
private:
std::string name_;
std::string bark_;
public:
Dog(std::string name, std::string bark = "Wang! Wang wang wang");
void barking();
};
cpp
#include "cat.h"
#include <iostream>
Cat::Cat(std::string name, std::string bark) : name_(name), bark_(bark) {}
void Cat::bark() {
std::cout << bark_ << std::endl;
}
cpp
#include "dog.h"
#include <iostream>
Dog::Dog(std::string name, std::string bark) : name_(name), bark_(bark) {}
void Dog::barking() {
std::cout << bark_ << std::endl;
}
使用CMake进行构建并运行
shell
$ ls
CMakeLists.txt include src
$ cmake -B build
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zm/code/cmake/projects/ch04_01/build
$ cmake --build build
[ 16%] Building CXX object CMakeFiles/animal_static.dir/src/cat.cpp.o
[ 33%] Building CXX object CMakeFiles/animal_static.dir/src/dog.cpp.o
[ 50%] Linking CXX static library /home/zm/code/cmake/projects/ch04_01/lib/libanimal.a
[ 50%] Built target animal_static
[ 66%] Building CXX object CMakeFiles/animal.dir/src/cat.cpp.o
[ 83%] Building CXX object CMakeFiles/animal.dir/src/dog.cpp.o
[100%] Linking CXX shared library /home/zm/code/cmake/projects/ch04_01/lib/libanimal.so
[100%] Built target animal
$ ls
CMakeLists.txt build include lib src
$ tree -I build
.
├── CMakeLists.txt
├── include
│ ├── cat.h
│ └── dog.h
├── lib
│ ├── libanimal.a
│ └── libanimal.so
└── src
├── cat.cpp
└── dog.cpp
4 directories, 7 files
CMake如何调用静/动态库
静态库调用流程
- 引入头文件
- 链接静态库
- 生成可执行二进制文件
动态库调用流程
- 引入头文件
- 声明库目录
- 生成可执行二进制文件
- 链接动态库
直接测试
现在有以下目录结构及代码环境
cmake
# 配置CMake的最小版本
cmake_minimum_required(VERSION 3.20.0)
# 配置项目名称
project(test)
# 添加了头文件引入目录,编写代码的时间可以省略目录前缀了
include_directories(test PUBLIC ${PROJECT_SOURCE_DIR}/include)
# 链接静态库
# link_directories(${PROJECT_SOURCE_DIR}/lib)
# link_libraries(animal)
# add_executable(test main.cpp)
# 链接动态库
# link_directories(${PROJECT_SOURCE_DIR}/lib)
# add_executable(test main.cpp)
# target_link_libraries(test PUBLIC animal)
link_directories(${PROJECT_SOURCE_DIR}/lib)
add_executable(test main.cpp)
# 链接动静态库
target_link_libraries(test PUBLIC cat dog)
cpp
#pragma once
#include <string>
class Cat {
private:
std::string name_;
std::string bark_;
public:
Cat(std::string name, std::string bark = "Miao~ miao~");
void bark();
};
cpp
#pragma once
#include <string>
class Dog {
private:
std::string name_;
std::string bark_;
public:
Dog(std::string name, std::string bark = "Wang! Wang wang wang");
void barking();
};
cpp
#include "cat.h"
#include "dog.h"
int main(int argc, char *argv[]) {
Dog dog("旺财");
dog.barking();
Cat cat("小橘");
cat.bark();
return 0;
}
使用CMake进行构建并运行
shell
$ cmake -B build
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zm/code/cmake/projects/ch04_02/build
$ cmake --build build
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Linking CXX executable test
[100%] Built target test
$ build/test
Wang! Wang wang wang
Miao~ miao~