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.cpp 4 directories, 4 files cmake_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 <iostream> #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.marks make -f CMakeFiles/Makefile2 all make[1]: Entering directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build' make -f CMakeFiles/hello_library.dir/build.make CMakeFiles/hello_library.dir/depend make[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_library make[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build' make -f CMakeFiles/hello_library.dir/build.make CMakeFiles/hello_library.dir/build make[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.a CMakeFiles/hello_library.dir/src/Hello.cpp.o /usr/bin/ranlib libhello_library.a make[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build' [ 50%] Built target hello_library make -f CMakeFiles/hello_binary.dir/build.make CMakeFiles/hello_binary.dir/depend make[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_binary make[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build' make -f CMakeFiles/hello_binary.dir/build.make CMakeFiles/hello_binary.dir/build make[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_binary libhello_library.a make[2]: Leaving directory '/mnt/d/Project/Cmake_examples/cmake_basics_03/build' [100%] Built target hello_binary make[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 0 ln28@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$ ls CMakeCache.txt CMakeFiles Makefile cmake_install.cmake hello_binary libhello_library.a ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$ ./hello_binary Hello 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_binary ln28@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_binary Install the project... -- Install configuration: "" -- Installing: /usr/local/lib/libhello_library.a CMake 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 1 ln28@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_binary Install the project... -- Install configuration: "" -- Installing: /usr/local/lib/libhello_library.a -- Installing: /usr/local/bin/hello_binary ln28@DESKTOP-FS9U3GT:/mnt/d/Project/Cmake_examples/cmake_basics_03/build$
轻轻松松搞定 ~