唠叨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的广告~ 如不喜欢请忽视!

先写到这里了,有其它想法再添加。

相关文章
相关标签/搜索