CMake基础(3)静态库
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$
轻轻松松搞定 ~