linux 环境使用 cmake 编译大型项目
1.一个简单的实例
使用 cmake 编译大型项目非常方便,做个简单的记录。
建立一个目录 win,这里面是工程文件。win 的目录如下:
win
\-- CMakeLists.txt
|-- build.sh
|-- libs 外部库
|-- src
|-- CMakeLists.txt
|-- common 公用头文件
|-- win98 win98工程
| |-- CMakeLists.txt
| |-- main.cc
| |-- win98.h
| \-- win98.cc
|
|-- win2000 win2000工程
|-- CMakeLists.txt
|-- main.cc
|-- win2000.h
\-- win2000.cc
win、src、win98、win2000 四个目录下都有一个 CMakeLists.txt 文件,该文件是必须的,cmake 根据这个文件来生成 Makefile。
win98 的CMakeLists.txt 内容如下
add_executable(win98
main.cc
win98.cc
)
假设 win2000 加入了新的网络功能,链接时需要用到 network 这个库文件,那么需要在 CMakeLists.txt 中指明
add_executable(robot
main.cc
win2000.cc
)
target_link_libraries(win2000 network)
src 目录下的 CMakeLists.txt 需要把它下属需要编译的目录都指定
add_subdirectory(win98)
add_subdirectory(win2000)
在 win 目录下的 CMakeLists.txt 文件内容复杂一点,下面是个简单的例子
# 指定版本和项目名称
cmake_minimum_required(VERSION 2.6)
project(windows CXX)
# 指定源码目录
add_subdirectory(src)
在 win 目录下运行
cmake . 后面有个点
make
整个工程编译完成,在 win98 和 win2000 下面就可以得到执行文件。
2.结合 Shell 脚本
上面用到的方法已经可以顺利编译工程,有个问题是,编译产生的中间文件都在源代码目录下,让目录混乱,如果把中间文件放在其他目录,可以保证源代码目录下是整洁的。
假设中间目录是 wintemp 和 win 目录同级。在 win 目录下添加 build.sh 文件,内容是
#!/bin/sh
set -x
SOURCE_DIR=`pwd`
BINARY_DIR=`pwd`
BUILD_DIR=${BUILD_DIR:-../wintemp}
mkdir -p $BUILD_DIR/$BUILD_TYPE && cd $BUILD_DIR/$BUILD_TYPE && cmake -DBINARY_DIR=$BINARY_DIR -DSOURCE_DIR=$SOURCE_DIR $SOURCE_DIR && make $*
执行这个脚本,可以看到中间文件全部都在 wintemp 目录。还可以指定可执行文件的路径
# 指定版本和项目名称
cmake_minimum_required(VERSION 2.6)
project(windows CXX)
# 指定生成的执行文件路径
set(EXECUTABLE_OUTPUT_PATH ${SOURCE_DIR}/bin)
# 指定源码目录
add_subdirectory(src)
如此一来,生成的执行文件就在源码目录下。
3.宏参数
多个项目存在共用代码的情况,举个最简单的例子,win98 和 win2000 共用 common/win.h 文件,这个文件里面定义了微软操作系统代号,比如 “win98”,”win2000”,很自然的可以想到用宏处理这个部分。
#ifdef __WIN98__
#define SYSNAME "win98"
#endif
#ifdef __WIN2000__
#define SYSNAME "win2000"
#endif
那么如何在项目中定义各自的编译参数呢?可以用 set_target_properties 这个方法。
在 win98 目录中的 CMakeLists.txt 中加上
set_target_properties(win98 PROPERTIES COMPILE_DEFINITIONS "__WIN98__")
在 win2000 目录中的 CMakeLists.txt 中加上
set_target_properties(win2000 PROPERTIES COMPILE_DEFINITIONS "__WIN2000__")
这样配置,win98 和 win2000 两个项目同时包含 common/win.h,可以得到不同的定义结果。
4.编译短小程序
程序员都会有一些目录,里面是自己写的短小代码,用以测试语法,函数用法等等。利用 cmake 可以很方便的编译这些细小的文件。
假设在 src 目录下存在 a.cc, b.cc, c.cc 等多个文件,每个文件都是一个独立的小程序,在 src 下建立的 CMakeLists.txt 中可以写一个脚本,将它们分别编程成对应的执行文件。
aux_source_directory (. filelist)
foreach(filename ${filelist})
string( REGEX MATCH "([a-z_]+)" binname ${filename} )
message( ${binname} )
add_executable(${binname} ${filename})
endforeach()
最后附上一个 CMakeLists.txt 的 例子,我从中收益良多。