C++开发(四)
C++开发(四)
find_package
CMake中find_package
这个命令,实际上是根据指定的包名查找与该包名对应的CMake模块文件(Find<PackageName>.cmake
)或配置文件(<PackageName>Config.cmake
)。CMake自带了一些库的查找模块,这些模块文件通常位于CMake的模块路径中。
如果自己安装的第三方包没有把这个文件弄到CMake的模块路径中,这时候就需要我们手动指定一个包含了对应.cmake
文件的路径:
1 | set(PYBIND11_ROOT "D:/Anaconda3/envs/PhononMC/Lib/site-packages/pybind11/share/cmake/pybind11") |
著注意不是这个包的根路径,而是包含了对应.cmake
文件的路径。
如果找到了 Find<PackageName>.cmake
文件,CMake
会执行这个文件中的逻辑。通常,该文件会尝试通过环境变量、系统默认路径或用户指定的路径来查找包的安装位置。
如果找到了 <PackageName>Config.cmake
文件,CMake
会直接加载该文件,通常该文件由库的开发者或安装脚本生成,包含了该库的详细信息,如库文件路径、头文件路径、依赖关系等。
一旦找到库或软件包,find_package
会设置一些变量,这些变量通常包括:
<PackageName>_FOUND
: 指示是否成功找到了指定的包。<PackageName>_INCLUDE_DIRS
或<PackageName>_INCLUDES
: 该包的头文件目录。<PackageName>_LIBRARIES
: 该包的库文件列表。<PackageName>_DEFINITIONS
: 该包需要的编译选项或预处理宏。
如果没有找到库或软件包,这些变量通常不会被设置,且
find_package
会返回
NOT_FOUND
。另外,一些包还会定义一些CMake宏或者函数,用于执行一些特定的操作。比如对于Pybind11,就提供了一个帮助创建Python模块的函数pybind11_add_module
。他会设置所有必要的编译选项、链接库和目标属性,以确保生成的模块可以正确地导入到Python中;还有常用的比如pybind11::module
,大概定义了需要的库一类的。
add_library
add_library
是CMake中的一个核心命令,用于定义一个库目标(静态库、共享库或模块库)。add_library
的基本用法是:
1 | add_library(<name> [STATIC | SHARED | MODULE] |
<name>
:库的名称。将会生成名为
lib<name>.a
、lib<name>.so
、<name>.dll
等的文件,具体取决于库的类型和平台。
STATIC
:生成静态库(.lib
或
.a
)。
SHARED
:生成共享库(.dll
、.so
、.dylib
)。
MODULE
:生成模块库。模块库是共享库,但不支持动态链接,通常用于插件系统。对于
Python 扩展模块等情况,使用 MODULE
是合适的。
EXCLUDE_FROM_ALL
:该库不会默认作为 all
目标的一部分构建,除非明确要求。
STATIC:
- 静态库在编译时会将所有相关的代码打包到一个二进制文件中。这个库在链接到可执行文件时被包含在内。
- 生成的文件通常是
lib<name>.a
或者name.lib
。
SHARED:
- 共享库会在运行时被动态链接。这种库可以被多个可执行文件共享,而不需要每个可执行文件都包含库的代码。
- 生成的文件通常是
lib<name>.so
(Linux)、<name>.dll
(Windows)或lib<name>.dylib
(macOS)。
MODULE:
- 模块库是动态链接库,但不在标准的链接过程中使用。它们通常用于插件或扩展模块(如 Python 扩展模块)。
- 生成的文件通常是平台特定的动态库格式,但它们的使用方式不同于
SHARED
库。例如,在 Python 扩展模块中,生成的文件是.pyd
(Windows)或.so
(Linux)。
Pybind11
pybind11
非常轻量,它实际上就是一堆头文件,不是像许多其他库那样需要编译成静态库或动态库来链接使用。在使用
pybind11
时,主要的工作就是包含它的头文件,并且在 CMake
或其他构建系统中设置好包含路径。pybind11_add_module
这样的工具会自动处理这些设置。
例如,在 CMake 中你只需要这样做:
1 | find_package(pybind11 REQUIRED) |
CMake 会处理 pybind11
的相关依赖。另外,其实在使用
pybind11
时,唯一需要额外链接的库就是 Python
本身的库。具体来说,pybind11
只依赖于 Python
的开发环境,这包括:
- Python 头文件:用于包含 Python C API,通常在 Python
的
include
目录中,例如Python.h
。 - Python 库文件:通常是
pythonX.lib
或者libpythonX.Y.so
这样的库文件,用于链接 Python 的运行时库。