0x01 介绍

在 CMake 中,静态库是一种特殊的目标文件,它与共享库和可执行文件不同,在链接时需要手动添加。静态库通常以 .a 或 .lib 结尾,可以通过 CMake 的 add_library() 命令添加。

0x01以下内容为补充知识点 , 学习静态库只看0x02示例就行。

add_library

CMake 还提供了一些其他的库类型,例如共享库(.so 或 .dll)、模块库(.mod)和对象库(.o)。可以根据实际需求选择适当的库类型。在 CMake 中,你可以使用 add_library() 命令来添加不同类型的库

# 添加静态库

add_library(MyStaticLib STATIC src/MyStaticLib.cpp)

# 添加共享库

add_library(MySharedLib SHARED src/MySharedLib.cpp)

# 添加模块库

add_library(MyModuleLib MODULE src/MyModuleLib.cpp)

# 添加对象库

add_library(MyObjectLib OBJECT src/MyObjectLib.cpp)

target_link_libraries

添加完库之后 , 可以通过 target_link_libraries() 命令添加链接。使用静态库的优点是可以将代码和库文件打包在一起,避免了动态库版本的冲突问题。

静态库可以在链接时使用绝对路径或者相对路径来指定,例如:

MyApp 是要链接静态库的目标文件,/path/to/MyLib、../lib/MyLib 和 $ENV{MY_LIB_PATH} 是静态库的路径。

# 使用绝对路径链接静态库

target_link_libraries(MyApp /path/to/MyLib)

# 使用相对路径链接静态库

target_link_libraries(MyApp ../lib/MyLib)

# 使用环境变量链接静态库

# 在系统的环境变量中设置 MY_LIB_PATH 变量,并在 CMake 中使用 $ENV{MY_LIB_PATH} 来引用该变量。

target_link_libraries(MyApp $ENV{MY_LIB_PATH})

link_directories

可以通过 link_directories() 命令来指定静态库的搜索路径,例如:

# 添加静态库的搜索路径,

link_directories(/usr/local/lib)

# 使用静态库的名称链接静态库

target_link_libraries(MyApp MyLib)

/usr/local/lib是静态库的搜索路径,MyLib 是静态库的名称。通过使用 link_directories() 命令,可

以避免在 target_link_libraries() 中指定完整的静态库路径。

0x02 示例

下面是一个简单的demo,使用 CMake 构建一个静态库:

本教程中的文件如下:

ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03$ tree.├── CMakeLists.txt├── build├── include│ └── static│ └── Hello.h└── src├── Hello.cpp└── main.cpp4 directories, 4 filescmake_minimum_required(VERSION 3.1)project(hello_library)# 定义库的名称为 hello_library#>>>>>>> hello_library 是库的名称,STATIC 表示构建静态库,src/Hello.cpp 是库文件的路径。add_library(hello_library STATIC src/Hello.cpp)# 添加头文件目录target_include_directories(hello_library PUBLIC ${PROJECT_SOURCE_DIR}/include)# 定义一个可执行文件add_executable(hello_binary src/main.cpp)message(STATUS ${hello_binary})# 安装静态库到 /usr/local/lib 目录install(TARGETS hello_library DESTINATION /usr/local/lib)# 安装可执行文件到 /usr/local/bin 目录install(TARGETS hello_binary DESTINATION /usr/local/bin)# 将静态库 MyLib 链接到可执行文件 MyApp 上target_link_libraries(hello_binary PRIVATE hello_library)

hello_binary 是可执行文件的名称,src/main.cpp 是可执行文件的源文件,通过 target_link_libraries() 命令将静态库 hello_library 链静态库可以通过 add_library() 命令添加,并在链接时通过 target_link_libraries() 命令添加链接。

使用静态库的优点是可以将代码和库文件打包在一起,避免了动态库版本的冲突问题。

例如,应用程序依赖于多个库时,如果使用静态库,你可以将这些库打包到应用程序中,这样用户可以直接下载应用程序并运行,不需要额外的安装和配置。

同时,静态库也有一些缺点,比如体积会比动态库大,链接时间会比动态库长。使用静态库的优点是可以将代码和库文件打包在一起,避免了动态库版本的冲突问题。

#ifndef __HELLO_H__#define __HELLO_H__class Hello{public:void print();};#endif #include #include "static/Hello.h"void Hello::print(){std::cout << "Hello Static Library!" << std::endl;}#include "static/Hello.h"int main(int argc, char *argv[]){Hello hi;hi.print();return 0;}

执行 cmake .. && make -j24 VERBOSE=1

ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$ cmake .. && make -j24 VERBOSE=1---- Configuring done-- Generating done-- Build files have been written to: /mnt/d/Project/Cmake_examples/cmake_basics_03/build/usr/bin/cmake -S/mnt/d/Project/Cmake_examples/cmake_basics_03 -B/mnt/d/Project/Cmake_examples/cmake_basics_03/build --check-build-system CMakeFiles/Makefile.cmake 0/usr/bin/cmake -E cmake_progress_start /mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles /mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/progress.marksmake -f CMakeFiles/Makefile2 allmake[1]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'make -f CMakeFiles/hello_library.dir/build.make CMakeFiles/hello_library.dir/dependmake[2]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'cd /mnt/d/Project/Cmake_examples/cmake_basics_03/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /mnt/d/Project/Cmake_examples/cmake_basics_03 /mnt/d/Project/Cmake_examples/cmake_basics_03 /mnt/d/Project/Cmake_examples/cmake_basics_03/build /mnt/d/Project/Cmake_examples/cmake_basics_03/build /mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_library.dir/DependInfo.cmake --color=Dependee "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_library.dir/DependInfo.cmake" is newer than depender "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_library.dir/depend.internal".Dependee "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_library.dir/depend.internal".Scanning dependencies of target hello_librarymake[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'make -f CMakeFiles/hello_library.dir/build.make CMakeFiles/hello_library.dir/buildmake[2]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'[ 25%] Building CXX object CMakeFiles/hello_library.dir/src/Hello.cpp.o/usr/bin/c++ -I/mnt/d/Project/Cmake_examples/cmake_basics_03/include -o CMakeFiles/hello_library.dir/src/Hello.cpp.o -c /mnt/d/Project/Cmake_examples/cmake_basics_03/src/Hello.cpp[ 50%] Linking CXX static library libhello_library.a/usr/bin/cmake -P CMakeFiles/hello_library.dir/cmake_clean_target.cmake/usr/bin/cmake -E cmake_link_script CMakeFiles/hello_library.dir/link.txt --verbose=1/usr/bin/ar qc libhello_library.aCMakeFiles/hello_library.dir/src/Hello.cpp.o/usr/bin/ranlib libhello_library.amake[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'[ 50%] Built target hello_librarymake -f CMakeFiles/hello_binary.dir/build.make CMakeFiles/hello_binary.dir/dependmake[2]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'cd /mnt/d/Project/Cmake_examples/cmake_basics_03/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /mnt/d/Project/Cmake_examples/cmake_basics_03 /mnt/d/Project/Cmake_examples/cmake_basics_03 /mnt/d/Project/Cmake_examples/cmake_basics_03/build /mnt/d/Project/Cmake_examples/cmake_basics_03/build /mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_binary.dir/DependInfo.cmake --color=Dependee "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_binary.dir/DependInfo.cmake" is newer than depender "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_binary.dir/depend.internal".Dependee "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles/hello_binary.dir/depend.internal".Scanning dependencies of target hello_binarymake[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'make -f CMakeFiles/hello_binary.dir/build.make CMakeFiles/hello_binary.dir/buildmake[2]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'[ 75%] Building CXX object CMakeFiles/hello_binary.dir/src/main.cpp.o/usr/bin/c++ -I/mnt/d/Project/Cmake_examples/cmake_basics_03/include -o CMakeFiles/hello_binary.dir/src/main.cpp.o -c /mnt/d/Project/Cmake_examples/cmake_basics_03/src/main.cpp[100%] Linking CXX executable hello_binary/usr/bin/cmake -E cmake_link_script CMakeFiles/hello_binary.dir/link.txt --verbose=1/usr/bin/c++-rdynamic CMakeFiles/hello_binary.dir/src/main.cpp.o-o hello_binarylibhello_library.amake[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'[100%] Built target hello_binarymake[1]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build'/usr/bin/cmake -E cmake_progress_start /mnt/d/Project/Cmake_examples/cmake_basics_03/build/CMakeFiles 0ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$

最终得到hello_binary和 libhello_library.a, 执行编译出的可执行文件

ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$ lsCMakeCache.txtCMakeFilesMakefilecmake_install.cmakehello_binarylibhello_library.aln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$ ./hello_binaryHello Static Library!

在 CMake 中,你可以使用 install() 命令将静态库安装到 /usr/local/lib 目录,例如:

修改CMakeLists.txt文件增加以下内容

# 安装静态库到 /usr/local/lib 目录install(TARGETS hello_library DESTINATION /usr/local/lib)# 安装可执行文件到 /usr/local/bin 目录install(TARGETS hello_binary DESTINATION /usr/local/bin)

在上面的例子中,hello_library 是静态库的名称,/usr/local/lib 是安装目录。通过 install() 命令,可以将静态库安装到指定的目录中。

在执行 cmake 命令时,CMake 会根据你的 CMakeLists.txt 文件中的内容生成安装脚本。你可以通过 make install 命令来安装静态库。例如,你可以运行下面的命令:

cmake .. && make -j24 install 主要是install , 但这个make install没有权限需要加sudo , 重新来执行以下

cmake .. && sudo make -j24 install看到了吗 , 生成文件到指定路径下了 , 你可以在不同的目录下执行hello_binary了。

Install the project...-- Install configuration: ""-- Installing: /usr/local/lib/libhello_library.a-- Installing: /usr/local/bin/hello_binaryln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$ cmake .. && make -j24 install---- Configuring done-- Generating done-- Build files have been written to: /mnt/d/Project/Cmake_examples/cmake_basics_03/build[ 50%] Built target hello_library[100%] Built target hello_binaryInstall the project...-- Install configuration: ""-- Installing: /usr/local/lib/libhello_library.aCMake Error at cmake_install.cmake:49 (file):file INSTALL cannot copy file"/mnt/d/Project/Cmake_examples/cmake_basics_03/build/libhello_library.a" to"/usr/local/lib/libhello_library.a": Permission denied.make: *** [Makefile:86: install] Error 1ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$cmake .. && sudo make -j24 install---- Configuring done-- Generating done-- Build files have been written to: /mnt/d/Project/Cmake_examples/cmake_basics_03/build[sudo] password for ln28:[ 50%] Built target hello_library[100%] Built target hello_binaryInstall the project...-- Install configuration: ""-- Installing: /usr/local/lib/libhello_library.a-- Installing: /usr/local/bin/hello_binaryln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$

轻轻松松搞定 ~