簡體   English   中英

CMake和FIND_PACKAGE

[英]CMake and FIND_PACKAGE

確保cmake僅從特定根目錄中查找庫和標頭的最佳方法是什么。

假如說:

  • 我們只想查看特定目錄(例如:/ mysdkroot /)
  • 我們要忽略不在特定目錄中的所有文件(例如,不應使用/ usr / lib或/ usr / include,而應僅使用/ mysdkroot /)
  • 使用庫提供的find_package()功能,而不是在cmake上找到文件或標頭的特定位置
  • 我們不編輯庫制造商提供的FindXXX.cmake或xxxConfig.cmake
  • 重要的是,我不想編輯每個查找包/文件/ lib的調用,指定要搜索的路徑

我可以使用NO_DEFAULT_PATH並指定查找路徑來完成一半,但我對此沒有完整的證明解決方案,因為我始終依賴於FindXXX.cmake或xxxConfig.cmake的實現方式。 例如,如果調試/發布文件具有不同的名稱,例如,在我的/ mysdkroot /中,我僅具有調試文件,並且在系統中僅存在發布,則對於某些庫,它可能會首先找到該發布,而不是首先找到調試,這是因為我無法將搜索范圍縮小到該文件夾​​。

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.cmakefindXX.cmakefindXX.cmake試圖在您的SDK路徑之外查找庫。

首先, XX-config.cmake通常行為正確。 如果找到了XX-config.cmake ,它將不會嘗試在路徑之外查找庫。 它已經知道在哪里可以找到那些庫。

然后,您擁有的FindXX.cmake可能會出現不正確的行為,因為它們主要是在不同的cmake時代用手寫的。

我的建議是替換行為不理想的模塊。 只需提供自己的自定義FindXX.cmake模塊即可正常運行。 如果維護者提供的服務沒有按照您的意願進行,請不要使用它們,只需提供您自己的服務即可。

確保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_PATHCMAKE_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_*命令,但沒有什么能夠阻止以不同的方式寫這些腳本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM