*Config.cmake或Find*.cmake的编写
当使用
vcpkg
安装detours
时,如果find_package
未能找到它,这通常意味着这个库可能没有提供CMake的配置文件(*Config.cmake
或Find*.cmake
)。vcpkg
通常会提供这些文件,但不是所有库都会这么做。
在这种情况下,您有以下几种选择:
-
手动指定库和头文件的路径:
在您的
CMakeLists.txt
中,您可以直接指定头文件和库文件的路径。include_directories("${VCPKG_ROOT}/installed/x64-windows-static/include") link_directories("${VCPKG_ROOT}/installed/x64-windows-static/lib") add_executable(MyTarget your_source_files_here) target_link_libraries(MyTarget detours)
在这里,
VCPKG_ROOT
是您的vcpkg
安装路径。 -
编写自己的
FindDetours.cmake
:如果你喜欢
find_package
的标准化方式,你可以编写一个自定义的FindDetours.cmake
文件,并把它放在你的项目中,然后用list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/your/path/to")
来添加到CMAKE_MODULE_PATH
。
编写自己的FindDetours.cmake
# 设置库的名称
set(DETOURS_LIBRARY_NAME detours)
# 尝试查找库文件
find_library(DETOURS_LIBRARY
NAMES ${DETOURS_LIBRARY_NAME}
PATHS ${VCPKG_ROOT}/installed/x64-windows-static/lib
NO_DEFAULT_PATH
)
# 尝试查找头文件
find_path(DETOURS_INCLUDE_DIR
NAMES detours.h
PATHS ${VCPKG_ROOT}/installed/x64-windows-static/include
NO_DEFAULT_PATH
)
# 确定是否找到了库和头文件
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Detours
DEFAULT_MSG
DETOURS_LIBRARY DETOURS_INCLUDE_DIR
)
# 设置导入的目标
if(DETOURS_FOUND AND NOT TARGET Detours::Detours)
add_library(Detours::Detours STATIC IMPORTED)
set_target_properties(Detours::Detours PROPERTIES
IMPORTED_LOCATION ${DETOURS_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${DETOURS_INCLUDE_DIR}
)
endif()
1. 目录的结构树如下
├── CMakeLists.txt
├── CMakeModules
│ └── FindDetours.cmake
├── DetoureTerminateProcess.cpp
└── DetoureTerminateProcess.h
2. CMakeLists.txt的内容如下
# CMakeList.txt: DetoureTerminateProcess 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
# 将源代码添加到此项目的可执行文件。
# add_executable (DetoureTerminateProcess "DetoureTerminateProcess.cpp" "DetoureTerminateProcess.h")
add_library (DetoureTerminateProcess SHARED "DetoureTerminateProcess.cpp" "DetoureTerminateProcess.h")
if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET DetoureTerminateProcess PROPERTY CXX_STANDARD 20)
endif()
set(VCPKG_ROOT "D:/vcpkg")
# TODO: 如有需要,请添加测试并安装目标。
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
find_package(Detours REQUIRED)
target_link_libraries(DetoureTerminateProcess
PRIVATE
Detours::Detours
)
3. 对于FindDetours.cmake的解释
确定库文件:
根据CMAKE_BUILD_TYPE
来动态选择debug或release版本的库。
if (CMAKE_BUILD_TYPE MATCHES Debug)
find_library(DETOURS_LIBRARY
NAMES ${DETOURS_LIBRARY_NAME}
PATHS ${VCPKG_ROOT}/installed/x64-windows-static/debug/lib
NO_DEFAULT_PATH
)
else()
find_library(DETOURS_LIBRARY
NAMES ${DETOURS_LIBRARY_NAME}
PATHS ${VCPKG_ROOT}/installed/x64-windows-static/lib
NO_DEFAULT_PATH
)
endif()
确定头文件:
对于头文件通常不需要区分Debug
和Release
,因为它们通常都是相同的。
find_path(DETOURS_INCLUDE_DIR
NAMES detours.h detver.h
PATHS ${VCPKG_ROOT}/installed/x64-windows-static/include/detours
NO_DEFAULT_PATH
)
对于find_library、find_path中NO_DEFAULT_PATH的理解:
NO_DEFAULT_PATH
是find_library
、find_path
以及其他一些find_*
CMake命令中的一个选项。当你使用这个选项,CMake会修改其默认的查找行为。通常,当你使用例如
find_library
或find_path
这类的命令时,CMake会在一系列预定义的路径中查找所需的文件或库。这些预定义的路径包括例如/usr/lib
或/usr/local/lib
这样的系统目录,也包括一些CMake特定的路径。但是,有时你可能只想在你明确指定的路径中查找某些东西,而不希望CMake在其他任何地方查找。这就是
NO_DEFAULT_PATH
选项的用处。当你使用这个选项时,CMake只会在你明确指定的PATHS
或HINTS
参数中提供的路径中查找,而不会去任何其他默认的查找路径。所以,理解
NO_DEFAULT_PATH
的关键是:它让你能够更精确地控制CMake的查找行为,确保只在你明确提供的路径中查找,而不是在其他任何默认路径中。这在某些情况下是很有用的,特别是当你不希望找到系统中的其他版本,或者当你知道所需的东西在一个非常特定的位置时。
确定是否找到库和头文件:
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Detours
DEFAULT_MSG
DETOURS_LIBRARY DETOURS_INCLUDE_DIR
)
include(FindPackageHandleStandardArgs)
是 CMake 中的一个指令,用于包含 FindPackageHandleStandardArgs.cmake
模块。这个模块提供了一个宏/函数,用于统一处理 find_package
的标准参数和结果。
让我们详细解释一下:
-
include(FileName)
:这是一个 CMake 命令,用于包含并执行指定的 CMake 脚本文件。此命令会查找
FileName
并执行其中的命令。 -
FindPackageHandleStandardArgs.cmake
:- 这是 CMake 自带的模块,提供了一个名为
find_package_handle_standard_args()
的宏/函数。 - 此函数主要用于处理
find_package
命令的结果,并生成适当的成功/失败消息。 - 它可以检查是否找到了所有必需的组件,并自动生成适当的
Found
变量(如DETOURS_FOUND
)。 - 它还提供了一种标准的方式来生成有关哪些组件找到或未找到的消息。
使用此模块的好处是为了确保所有的
find_package
命令在查找库和头文件时都有一致的行为和输出。在你给出的代码中,你可以看到
find_package_handle_standard_args
的实际使用:find_package_handle_standard_args(Detours DEFAULT_MSG DETOURS_LIBRARY DETOURS_INCLUDE_DIR )
这里,函数检查
DETOURS_LIBRARY
和DETOURS_INCLUDE_DIR
是否已被设置(意味着它们已被找到)。如果都被设置了,它会自动设置DETOURS_FOUND
为TRUE
。如果任何一个没有被设置,它会打印一个标准的错误消息,告诉你哪个组件没有被找到。设置导入目标:
- 这是 CMake 自带的模块,提供了一个名为
if (DETOURS_FOUND AND NOT TARGET Detours::Detours)
add_library(Detours::Detours STATIC IMPORTED)
set_target_properties(Detours::Detours PROPERTIES
IMPORTED_LOCATION ${DETOURS_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${DETOURS_INCLUDE_DIR}
)
endif()
这段代码是使用set_target_properties
命令为Detours::Detours
目标设置一些属性。在CMake中,目标可以是可执行文件、库或其他一些构建产物。这些属性告诉CMake如何处理这个目标。让我们逐行解释这段代码:
set_target_properties(Detours::Detours PROPERTIES
:这是设置Detours::Detours
目标属性的开始。PROPERTIES
关键字后面列出的是您要设置的属性名及其对应的值。IMPORTED_LOCATION ${DETOURS_LIBRARY}
:这是设置导入库的物理位置。当这是一个导入的目标时(例如,它不是由当前项目构建的,而是已经存在的库),这个属性告诉CMake库文件在文件系统上的位置。${DETOURS_LIBRARY}
是之前通过find_library
查找到的库文件的完整路径。INTERFACE_INCLUDE_DIRECTORIES ${DETOURS_INCLUDE_DIR}
:这指定了当其他目标链接到Detours::Detours
时,它们需要的头文件的位置。这意味着,当您链接到这个库时,这些目录将被添加到编译器的包含路径中,以便可以找到库的头文件。${DETOURS_INCLUDE_DIR}
是之前通过find_path
查找到的头文件目录。
这段代码的目的是为Detours::Detours
目标设置其库文件的位置和头文件的位置。这样,当其他目标在项目中链接到Detours::Detours
时,CMake将知道如何找到库和头文件,并将它们包含在构建过程中。