2015-05-28 38 views
3

我剛剛閱讀了關於CMake的配置文件包「概念」,這聽起來很有希望。我非常喜歡的是,如果我自己創建配置文件包,我可以指定它所依賴的其他包。我的問題是:如何創建一個「可重定位」並取決於查找模塊包(例如boost)的Config-File包?CMake:配置文件包依賴查找模塊包的推薦方式

更詳細地說:假設我想創建一個名爲HyDi的包。 cmake documentation很好地解釋了我可以如何自動創建相應的HydiConfig.cmake和HydiTargets.cmake文件。在的CMakeLists.txt的一個非常簡單的版本確實是這樣的:

project(HyDi) 

find_package(Boost COMPONENTS program_options) 
add_library(HyDi foo.cpp foo.hpp) 
target_include_directories(HyDi PUBLIC INTERFACE ${Boost_INCLUDE_DIRS}) 
target_link_libraries(HyDi ${Boost_LIBRARIES}) 
target_compile_options(HyDi INTERFACE PUBLIC "-std=c++11") 


install(TARGETS HyDi EXPORT HyDiTarget 
    LIBRARY DESTINATION lib 
    ARCHIVE DESTINATION lib 
    RUNTIME DESTINATION bin 
    INCLUDES DESTINATION include 
) 

install(FILES foo.hpp DESTINATION include) 

configure_file(cmake/HyDiConfig.cmake 
    "${CMAKE_CURRENT_BINARY_DIR}/HyDi/HyDiConfig.cmake" 
    COPYONLY 
) 

set(ConfigPackageLocation lib/cmake/HyDi) 
install(EXPORT HyDiTarget FILE HyDiTargets.cmake 
    NAMESPACE Upstream:: DESTINATION ${ConfigPackageLocation}) 
install(FILES cmake/HyDiConfig.cmake DESTINATION ${ConfigPackageLocation}) 

相應HydiConfig.cmake是:

include(CMakeFindDependencyMacro) 
find_dependency(Boost COMPONENTS program_options) 

include("${CMAKE_CURRENT_LIST_DIR}/HyDiTargets.cmake") 

但是如果我安裝這個庫中,HyDiTargets.cmake文件將包含包括硬編碼Boost庫的路徑,因此不可重定位。

請注意,cmake documentation給出了一個示例,說明如何不包含基本上是我的版本的boost庫。但不幸的是,他們沒有解釋如何更好地做到這一點。

我知道我可以使用cmake構建boost,然後可以將boost作爲配置文件包導入,以便我的HydiTargets.cmake可以重定位。但是這種方法不適用於提供Findxxx.cmake文件的每個其他庫。

+0

謝謝ruslo,但這種方法本質上意味着我將不得不使用cmake構建提升(這仍然是實驗性的) – craffael

+0

好吧,我剛剛又看了看獵人和肯定,爲推動這將是一種選擇。但是我沒有看到我如何爲我的其他七個外部庫(除非在Hunter中存在一個包)獲得一個cmake包(配置模式)。如果可能的話,我也想避免使用第三方cmake工具。 – craffael

+0

非常有趣的問題,我面臨同樣的問題。 [craffael](https://stackoverflow.com/users/2796908/craffael)你有想出一個解決方案? – kiki

回答

-2

其實CMake做到這一點是正確的,當注入一個「硬編碼」路徑來提高庫(和你做錯了)。因爲在你的庫被編譯和安裝之後,它應該「鏈接」到非常特別的boost版本(當它在你的庫編譯時) - 即它的頭文件和靜態/動態庫。考慮情況:在你的庫成功安裝之後,有人會並行安裝一個新版本的boost庫(或者你所依賴的任何其他第三方庫)(是的,boost和其他庫可以共存於同一個安裝前綴中)。爲了讓事情看起來像一個真實世界的例子,假設它與前一個版本ABI不兼容。現在,如果說「幸運」開發商想用你的(已編譯和安裝)庫(使用出口目標,並提供HyDiConfig.cmake),他會得到一個麻煩:

  • 您的圖書館已經鏈接到「以前」增強版本(記得ABI不兼容w /新版本);
  • 因此,當您以某種方式替換「硬編碼」路徑並且會找到更新的版本時(如您在HyDiConfig.cmake中所做的那樣),您的「幸運」客戶會因爲那個混亂而對您生氣!

這不僅是提升......同樣的政策對所有第三方庫:他們應該是一樣的,因爲它是在編譯的時刻(或者至少ABI兼容的,如果我們在運行時談論的動態鏈接,但這是一個單獨的故事)。此外,您的用戶可能甚至不在他的應用程序中使用boost(但安裝了多個版本) - 爲什麼你應該找到smth?你已經知道(感謝CMake和硬編碼路徑)你的庫需要什麼boost版本!所以在這種情況下尋找新的是完全錯誤的!這是「太遲了...... 你的圖書館已經編譯,鏈接和安裝!

另一種情況:他要用提振其他一些(新)版本...取決於find_package(boost)find_package(yourLib)結果順序可能會有所不同......但他會對你生氣呢!