Fork me on GitHub

cmake实践(一)

前期准备

系统环境: centos 7.2
安装cmake ref: CentOS之—— CentOS7源码安装cmake

cmake世界的HelloWorld

demo过程

  • 在centos系统的任意位置处创建cmake_learning文件夹:
  • 在文件夹下创建1个mian.c文件和1个CMakeLists.txt文件, 内容如下:
// main.c
#include <stdio.h>    

int main(){  
    printf("Hello World from Main!\n");  
    return 0;  
} 
//CMakeLists.txt
PROJECT (HELLO)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})
  • 开始构建
    当前目录运行命令: cmake .
    终端输出内容为:
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- This is BINARY dir /opt/learningNotes/cmake_learning
-- This is SOURCE dir /opt/learningNotes/cmake_learning
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/learningNotes/cmake_learning   

此时,当前目录生成若干文件:

CMakeCache.txt  cmake_install.cmake  main.c
CMakeFiles  CMakeLists.txt   Makefile

最重要的是生成了MakeFile文件,接着在当前目录继续输入命令: make
终端输出内容为:
本地1

(ps:如果想看到make构建的详细过程,可以使用make VERBOSE=1或者VERBOSE=1
make命令来进行构建。)
此时,目标文件hello已经生成于当前目录,运行该文件: ./hello
终端输出:
Hello World from Main!

简单解释

CMakeLists.txt是cmake的构建定义文件,文件名对大小写敏感。
当你的工程存在多级目录时,每个目录下都要存在一个CMakeLists.txt。
回顾一下CMakeLists.txt的内容:

//CMakeLists.txt
PROJECT (HELLO)
SET(SRC_LIST main.c)
MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR})
ADD_EXECUTABLE(hello ${SRC_LIST})

PROJECT指令

 PROJECT(工程名 [CXX] [C] [java])    //默认支持全语言  

该指令隐含地定义了2个cmake变量:

  • <projectname>_BINARY_DIR
  • <projectname>_SOURCE_DIR

而且,目前采用内部编译,这2个变量均指向当前目录,后面会涉及外部编译方式

同时,cmake 系统预定义了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR 变量,它们的值与上述2个变量一致

SET指令

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])    
set指令用来显示地定义变量 存在多个源文件时,定义为:
SET(SRC_LIST main.c t1.c t2,c)

MESSAGE指令

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...)
MESSAGE指令用于向终端输出用户定义的信息,包含了3种类型: SEND\_ERROR,产生错误,生成过程被跳过。 SATUS,输出前缀为\-的信息。 FATAL_ERROR,立即终止所有cmake过程 ### ADD_EXECUTABLE指令 ADD\_EXECUTABLE(hello ${SRC\_LIST}) 定义了这个工程会生成一个文件名为hello的可执行文件,相关的源文件是SRC\_LIST中定义的源文件列表, 本例中你也可以直接写成ADD_EXECUTABLE(hello main.c) ### 清理工程
 make clean 

基本语法规则

本地2
ps:
本地3

内部构建和外部构建

上述构建方式属于内部构建,但cmake强烈推荐外部构建方式

1,首先,请清除当前目录中除main.c CmakeLists.txt之外的所有中间文件,最关键的是CMakeCache.txt
2. 在当前目录下建立build子目录,当然你也可以在任何地方建立build目录,不一定必须在工程目录中
3.进入build目录,运行cmake ..  
(注意,..代表父目录,因为父目录存在我们需要的CMakeLists.txt,如果你在其他地方建立了build目录,需要运行cmake <工程的全路径>),查看一下build目录,就会发现了生成了编译需要的Makefile以及其他的中间文件
4.运行make构建工程,就会在当前目录(build目录)中获得目标文件hello

上述过程就是所谓的out-of-source外部编译,一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。通过这一点,也足以说服我们全部采用外部编译方式构建工程。
这里需要特别注意的是:
通过外部编译进行工程构建,HELLO_SOURCE_DIR仍然指代工程路径,即
/opt/learningNotes
而HELLO_BINARY_DIR则指代编译路径,即 /opt/learningNotes/build

------ Happy Ending Meet The Better You ------