CMake使用进阶

为什么使用CMake

CMake是跨平台的构建工具,公司主要使用这个工具生成,掌握了CMake用法觉得自动化构建还是很容易的

cmake使用方法

1.基本结构

1
2
3
4
5
6
7
8
- project
- includes
- CMakeLists.txt
- *.h
- src
- CMakeLists.txt
- *.cc
- CMakeLists.txt

  1. 依赖CMakeLists.txt文件,项目主目标一个,主目录可指定包含的子目录
  2. 在项目CMakeLists.txt中使用project指定项目名称,add_subdirectory添加子目录
  3. 子目录CMakeLists.txt从父目录CMakeLists.txt继承设置

2.语法

  • 注释: 行注释,以#开头

  • 变量

    • 使用set命令显式定义及赋值
    • 在非if语句中,使用${}引用
    • if中直接使用变量名引用
    • 后续的set命令会清理变量原来的值
  • command (args …)

    • 命令不分大小写
    • 参数使用空格分隔
    • 使用双引号引起参数中空格
  • set(var a;b;c) <=> set(var a b c)

    • 定义变量var并赋值为a;b;c这样一个string list
  • add_executable(${var}) <=> add_executable(a b c)

    • 变量使用${xxx}引用
  • 条件语句

1
2
3
4
5
6
7
if(var) #var非empty,0,FALSE
...
elseif()
...
else()
...
endif()
  • 循环语句
1
2
3
4
5
6
7
8
9
10
第一种:
set(var a b c)
foreach(f ${var})
...
endforeach(f)

第二种:
while()
...
endwhile()

3.内部变量

1
2
3
4
5
6
7

1. CMAKE_C_COMPILER/CMAKE_CXX_COMPILER 指定C/C++编译器
2. CMAKE_C_FLAGS/CMAKE_CXX_FLAGS 设置C/C++编译参数
3. EXECUTABLE_OUTPUT_PATH 可执行文件的存放路径
4. LIBRARY_OUTPUT_PATH 库文件存放路径
5. CMAKE_BUILD_TYPE 编译类型(Debug,Release)
6. BUILD_SHARED_LIBS 编译动态链接库(ON,OFF)

4.命令(不分大小写)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

project( test ) #指定项目名称,使用${test_SOURCE_DIR}表示项目根目录

include_directories #指定头文件的搜索路径

link_directories #指定动态链接库的搜索路径

add_subdirectory #包含子目录

add_executable #编译可执行程序,指定编译`add_executable(hello hello.cc header.cc)`

add_definitions #添加编译参数 `add_definitions("-Wall -g")`

target_link_libraries #添加链接库 `target_link_libraries( demo ${BOOST_LIBRARIES} )`

add_library #编译成静态库 `add_library(demo demo.cc)`

add_custom_target #添加自定义编译目标

set_target_properties #设置编译目标属性,OUTPUT_NAME,VERSION等

link_libraries(lib1 lib2 ) #所有编译目标链接相同的库

5.其他

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1. MESSAGE({SEND_ERROR|STATUS|FATAL_ERROR} "this is message")        #打印编译信息,FATAL_ERROR会停止编译

2. AUX_SOURCE_DIRECTORIES #获得目录下所有源文件,添加新文件需要重新运行cmake .

3. FILE(GLOB SRC_FILES RELATIVE ${CMAKE_CURRENT_SOUCE_DIR} *.cpp) #显式添加编译文件列表,添加新文件无需重新运行cmake .

4. FIND_LIBRARY(Boost COMPONENTS thread system log REQUIRED) #查找并添加动态库(添加一部分)

5. OPTION 条件编译
OPTION(DEBUG_mode "this is debug." ON)
IF(DEBUG_mode)
add_definitions(-DDEBUG)
ENDIF()

6. ADD_DEPENDENCIES 添加编译依赖项

7. SET_TARGET_PROPERTIES 设置目标文件目录

8. CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 设置cmake最小版本

9. LESS,GREATER,EQUAL 数字比较

10.STRLESSSTRGREATERSTREQUAL 字符串比较

6.C++ Server组使用范例

  • workspace

    • CMakeLists.txt #根目录cmake file
    • common_inc #头文件
    • common_lib #库文件
  • 编译common库

    • add_subdirectory(stt_common/branch/1.0)
    • add_subdirectory(stt_msgbus/branch/1.0_cluster)
    • add_subdirectory(stt_dy_common/trunk)
  • 编译具体项目

    • add_subdirectory(stt_dy_chatroom/trunk)

Win平台使用CMake

  • 像大多数开源软件一样,CMake和Unix/Linux的结合比Win好多了
  • 在Win下使用比较麻烦,当然这只是在链接各种第三方库的情况下
  • 而我们一般都在使用各种第三方库的情况下,CMake才比VS有优势
  • 下面将以CMake链接Boost的一个项目作为示例

语法规则

  • CMake的内建命令大部分都是通用的,但是对于Win下使用VS的编译器来说,需要注意以下几点:
    • 必须定义CMAKE_CXX_COMPILER为cl
    • 最好使用/EHsc的定义来避免链接的过程失败,因为VS有自己的安全检查方法
    • 可以使用WinDbg来确定可执行文件的依赖,然后针对性去除多余的LINK_LIBRARIES
    • 生成MakeFile或者VS的工程需要定义好平台架构,默认是x86,还可以定义Win64和arm,可以参阅cmake帮助

示例

  • 源文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/timer.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>


void test_timer(const boost::system::error_code& ec,boost::asio::deadline_timer& t,int& count)
{

if(!ec){
if(count++==5) return;
t.expires_from_now(boost::posix_time::seconds(1));
t.async_wait(boost::bind(&test_timer,boost::asio::placeholders::error,
boost::ref(t),boost::ref(count)));
std::cout<<"working\n";
}
}

int main(int argc, char const *argv[])
{

boost::asio::io_service io;


int count = 0;
boost::asio::deadline_timer tm(io);

tm.expires_from_now(boost::posix_time::seconds(1));
tm.async_wait(boost::bind(test_timer,boost::asio::placeholders::error,
boost::ref(tm),boost::ref(count)));
io.run();

return 0;
}
  • CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_COMPILER "cl")
set(CMAKE_CXX_FLAGS "/O2")
add_definitions("/EHsc")
#find_package(Boost COMPONENTS thread system REQUIRED)

include_directories(
D:\\boost_1_60_0
)

link_directories(
D:\\boost_1_60_0\\lib64-msvc-14.0
)

link_libraries(
boost_thread-vc140-mt-1_60
boost_system-vc140-mt-1_60
)

add_executable(test_vc 1.cc)
  • 构建过程
1
2
3
4
5
6
7
8
//生成VS2015 64位的应用,默认是x86
cmake -G "Visual Studio 14 2015 Win64" .
//VS编译打开目录下的解决方案,编译即可

//nmake使用,在有外部链接库的时候容易失败
cmake -G "NMake Makefiles" .
//找到对应平台的nmake命令,一定要一致
nmake

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 为什么使用CMake
  2. 2. cmake使用方法
    1. 2.1. 1.基本结构
    2. 2.2. 2.语法
    3. 2.3. 3.内部变量
    4. 2.4. 4.命令(不分大小写)
    5. 2.5. 5.其他
    6. 2.6. 6.C++ Server组使用范例
  3. 3. Win平台使用CMake
    1. 3.1. 语法规则
    2. 3.2. 示例
,