嘮叨CMake工具

CMake是一個跨平臺、開源的編譯管理軟件,英文就是cross-platform, open-source build system。它是在其它衆多編譯工具之上(如Make、Visual Studio、Xcode等)創建了一層封裝。用戶須要編寫和維護一個名爲CMakeLists.txt的文件,而後運行cmake命令生成相應的項目文件(如針對Make就是生成Makefile)。我本身之前也寫過一個相似的軟件,可是沒有支持,另外看到CMake後就放棄了。你們在用的時候通常會遇到以下問題:git

  • 多編程語言如何管理
  • 依賴庫的編譯選項如何管理

針對多編程語言,CMake已經作得很好了,只要在聲明項目的時候加上相應的語言就好了,如:github

project (項目名稱 C CXX Fortran)

而後列出須要編譯的程序文件,CMake會用相應的編譯器去編譯它們。這大大簡化了維護編譯文件的負擔,這一點也是我最爲欣賞的。編程

第二點其實更爲重要,也更爲頭痛。CMake提供了不少Find<XXX>.cmake模塊,號稱是方便用戶查找相應的依賴庫。好比我要用到C++中的Boost庫,只要寫以下語句:編程語言

find_package (Boost 1.55.0 REQUIRED
    COMPONENTS regex filesystem system timer date_time
)

它代表須要版本不能低於1.55.0Boost庫,使用了其中的regexfilesystemsystemtimerdate_timer子庫,相應的頭文件和庫文件的編譯選項會設置在以下兩個CMake變量:工具

Boost_INCLUDE_DIRS
Boost_LIBRARIES

用它們作相應設置,就可讓編譯器正確編譯:ui

include_directories (${Boost_INCLUDE_DIRS})
...
target_link_libraries (目標名
    ...
    ${Boost_LIBRARIES}
)

對於搜索我要多說一句,FindBoost.cmake會參考環境變量BOOST_ROOT,若是有該變量,那麼就使用它所指向的Boost。我我的以爲這個實際上是CMake的亮點,可是並非全部的Find<XXX>.cmake模塊都寫得很好,好比FindArmadillo.cmake,它就不參考ARMADILLO_ROOT環境變量,所以若是咱們安裝的Armadillo庫到一個非標準的路徑下,即便咱們設置了ARMADILLO_ROOT,CMake也是找不到它的。你會碰見惱人的錯誤:code

CMake Error at /opt/packman/cmake/3.2.1/share/cmake-3.2/Modules/FindPackageHandleStandardArgs.cmake:138 (message):
  Could NOT find Armadillo (missing: ARMADILLO_LIBRARY ARMADILLO_INCLUDE_DIR)
Call Stack (most recent call first):
  /opt/packman/cmake/3.2.1/share/cmake-3.2/Modules/FindPackageHandleStandardArgs.cmake:374 (_FPHSA_FAILURE_MESSAGE)
  /opt/packman/cmake/3.2.1/share/cmake-3.2/Modules/FindArmadillo.cmake:107 (find_package_handle_standard_args)
  external/geomtk/CMakeLists.txt:46 (find_package)

我就查看了CMake中的FindArmadillo.cmake文件,作了以下修改:orm

# UNIX paths are standard, no need to write.
find_library(ARMADILLO_LIBRARY
  NAMES armadillo

HINTS                 # <--
  ENV ARMADILLO_DIR   # <--
  ENV ARMADILLO_ROOT  # <--
PATH_SUFFIXES         # <--
  lib                 # <--
  lib64               # <--

  PATHS "$ENV{ProgramFiles}/Armadillo/lib"  "$ENV{ProgramFiles}/Armadillo/lib64" "$ENV{ProgramFiles}/Armadillo"
  )
find_path(ARMADILLO_INCLUDE_DIR
  NAMES armadillo

HINTS                 # <--
  ENV ARMADILLO_DIR   # <--
  ENV ARMADILLO_ROOT  # <--
PATH_SUFFIXES         # <--
  include             # <--

  PATHS "$ENV{ProgramFiles}/Armadillo/include"
  )

就能夠搜索到了。另外還有就是一個庫可能依賴許多其它庫,此時不能僅僅添加該庫,還要將它的全部依賴庫都添加進來才能正常編譯鏈接!例如GDAL庫,它依賴不少庫(不列舉了),若是這些庫不是放置在標準路徑下,那麼連接時就會出現著名的「找不到符號」的錯誤,所以我又對FindGDAL.cmake作了以下修改:get

exec_program(${GDAL_CONFIG} ARGS --dep-libs OUTPUT_VARIABLE GDAL_CONFIG_DEP_LIBS)
set(GDAL_LIBRARIES ${GDAL_LIBRARY} ${GDAL_CONFIG_DEP_LIBS})

即把GDAL依賴的庫(由gdal-config命令獲取)也添加到GDAL_LIBRARIES裏,就能夠了。編譯器

以上兩處修改我都放到了我所作的跨平臺、開源包管理器PACKMAN中了,所以凡是經過PACKMAN安裝的CMake都包含了這兩處修改~

$ packman install cmake

此處是對PACKMAN的廣告~ 如不喜歡請忽視!

先寫到這裏了,有其它想法再添加。

相關文章
相關標籤/搜索