确保cmake仅从特定根目录中查找库和标头的最佳方法是什么。
假设:
我可以使用NO_DEFAULT_PATH并指定查找路径来完成一半的工作,但是我对此没有完整的解决方案,因为我始终依赖于FindXXX.cmake或xxxConfig.cmake的实现方式。例如,如果调试/发布文件具有不同的名称,例如,在我的/ mysdkroot /中,我仅具有调试文件,并且在系统中仅存在发布,则对于某些库,它可能会首先找到该发布,而不是首先找到调试,这是因为我无法将搜索范围缩小到该文件夹。
答案 0 :(得分:3)
NO_DEFAULT_PATH
是一个好的开始。但是,我将启用一种查找软件包的方法,那就是使用CMAKE_PREFIX_PATH
:
NO_PACKAGE_ROOT_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_PACKAGE_REGISTRY
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_SYSTEM_PACKAGE_REGISTRY
这会禁用它们,除了CMAKE_PREFIX_PATH
中指定的路径。
然后将您的前缀路径设置为sdk:
set(CMAKE_PREFIX_PATH "/mysdkroot")
然后,实际上,您仍然取决于如何实现这些findXXX.cmake
和那些XXX-config.cmake
。幸运的是,您可以使用命令多态性完全改变其行为:
set(current-find-package "")
function(find_package)
set(current-find-package "${ARGV1}")
# The leading underscore mean the original command
_find_package(${ARGV})
endfunction()
# function usually used in findXX.cmake modules
function(find_library)
if("${current-find-package}" STREQUAL "SomePakage")
# TODO: remove unwanted paths in ARGV
_find_library(${ARGV} NO_DEFAULT_PATH)
endif()
endfunction()
尽管这可以解决问题,但我建议不要滥用,或者要非常小心使用它。您不想引入令人惊讶的行为。
您主要关注的是XX-config.cmake
和findXX.cmake
试图在您的SDK路径之外查找库。
首先,XX-config.cmake
通常行为正确。如果找到XX-config.cmake
,它将不会尝试在路径之外查找库。它已经知道在哪里可以找到那些库。
然后,FindXX.cmake
的行为可能不正确,因为它们主要是在不同的cmake时代手写的。
我的建议是替换行为不理想的模块。只需提供自己的自定义FindXX.cmake
模块即可正常运行。如果维护者提供的服务没有按照您的意愿进行,请不要使用它们,只需提供您自己的服务即可。
答案 1 :(得分:1)
确保cmake仅从特定的根目录中查找库和标头。
取决于“根目录”是真正的“根”的方式,您可以尝试将CMAKE_FIND_ROOT_PATH变量设置为该目录:
set(CMAKE_FIND_ROOT_PATH "/mysdkroot")
伴随将CMAKE_FIND_ROOT_PATH_MODE_*
变量设置为ONLY,您可以强制相应的find_*
命令仅在给定目录下搜索:
# 'find_path' will search only under CMAKE_FIND_ROOT_PATH.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "ONLY")
# 'find_library' will search only under CMAKE_FIND_ROOT_PATH.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY "ONLY")
# 'find_package' will search 'XXXConfig.cmake' (not 'FindXXX.cmake'!) only under CMAKE_FIND_ROOT_PATH.
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE "ONLY")
此方法的局限性在于CMake将CMAKE_FIND_ROOT_PATH
目录解释为文件系统根目录,而不是安装前缀。也就是说,CMake假定(在Linux环境上)库位于/mysdkroot/usr/lib
下,标头位于/mysdkroot/usr/include
下。
您可以结合使用CMAKE_FIND_ROOT_PATH
和CMAKE_PREFIX_PATH
设置来向CMake告知安装目录:
set(CMAKE_FIND_ROOT_PATH /mysdk)
set(CMAKE_PREFIX_PATH /root) # Not sure whether setting prefix to `/` would work.
具有与
相似的效果set(CMAKE_PREFIX_PATH /mysdk/root)
但是,如果CMake在给定的前缀下找不到某些内容,那么它将不会搜索/usr/include
(将CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
设置为ONLY
)。
相反,它将尝试/mysdk/usr/include
。而且,如果您的系统上没有给定的目录,则在该目录下找不到任何内容。
请注意,不能确定100%CMake所找到的内容都不会位于特定根目录之外。您可能希望FindXXX.cmake
以“正常”的方式编写,该方式使用find_*
命令,但是没有什么可以阻止这些脚本的编写方式不同。