CMake是一个跨平台、开源的编译管理软件,英文就是cross-platform, open-source build system。它是在其它众多编译工具之上(如Make、Visual Studio、Xcode等)建立了一层封装。用户需要编写和维护一个名为CMakeLists.txt
的文件,然后运行cmake
命令生成相应的项目文件(如针对Make就是生成Makefile
)。我自己以前也写过一个类似的软件,但是没有支持,另外看到CMake后就放弃了。大家在用的时候一般会遇到如下问题:
- 多编程语言如何管理
- 依赖库的编译选项如何管理
针对多编程语言,CMake已经做得很好了,只要在声明项目的时候加上相应的语言就行了,如:
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.0
的Boost
库,使用了其中的regex
,filesystem
,system
,timer
,date_timer
子库,相应的头文件和库文件的编译选项会设置在如下两个CMake变量:
Boost_INCLUDE_DIRS
Boost_LIBRARIES
用它们做相应设置,就可以让编译器正确编译:
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也是找不到它的。你会遇见恼人的错误:
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
文件,做了如下修改:
# 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
做了如下修改:
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的广告~ 如不喜欢请忽视!
先写到这里了,有其它想法再添加。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。