程序员应了解的那些事(59)之 cmake(安装 ~ 语法 ~ 实例)

目录

【cmake 安装】

1、使用yum安装

2、使用源码安装(当你想要获取更高版本的cmake)//源码安装三部曲 ./configure  ~ make  ~ make install

3、编写程序验证

【cmake 语法基础】

(1)cmake基本编写格式:

(2)定义变量

(3)cmake构建系统       

(4)外部构建 ※※

①message用法

②cmake_minimum_required (VERSION 2.6):

③ project (Tutorial)

④configure_file 

⑤include_directories这一行:include_directories("${PROJECT_BINARY_DIR}")

(5)CMake 链接第三方的库 ※(指定支持C++11)

举例 (1)链接libev, 如下:

举例(2)导入第三方库wfdb库:

(6)cmake:用add_subdirectory()添加外部项目文件夹

  ① INCLUDE_DIRECTORIES(添加头文件目录)

  ⑤联合示例: 

 【CMakeList.txt的简单实战】

<1>CMake 简介

<工程练习 - 1>

<工程练习 - 2>

<工程练习 - 3>


【cmake 安装】

1、使用yum安装

CentOS 7安装的命令为: sudo yum install cmake  
安装后查看版本为:    cmake version 2.8.12.2

2、使用源码安装(当你想要获取更高版本的cmake)//源码安装三部曲 ./configure  ~ make  ~ make install

$yum erase cmake//卸载原先cmake
$wget https://cmake.org/files/v3.9/cmake-3.9.0.tar.gz//下载
$tar xvf   cmake-3.9.0.tar.gz //解压
$cd cmake-3.9.0
$./configure
$make
$make install //在/usr/local/bin可以看到cmake可执行程序,添加cmake到PATH环境变量中
$cmake --version //查看版本为3.9.0

3、编写程序验证

$mkdir Test //新建一个工程目录,并进入目录
新建一个文件为main.c ,内容如下:

#include <stdio.h>
int main(){
printf("hello world");
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})

在Test目录中,执行
$cmake . //生成Makefile
$make    //生成可执行程序hello

$./hello //输出hello world,到此完成cmake3.9.0安装验证

【cmake 语法基础】

本节讲的命令格式遵循如下语法:(应该是比较通用的规则)

cmake能识别CMakeLists.txt和*.cmake格式的文件。cmake能够以三种方式 来组织文件,本系列主要以CMakeLists.txt的语法为主要讲解内容。

1、<Directory>
        当CMake处理一个项目时,入口点是一个名为CMakeLists.txt的源文件,这个一定是根目录下的CMakeLists.txt。这个文件包含整个工程的构建规范,当我们有多个子文件夹需要编译时,使用add_subdirectory(<dir_name>)命令来为构建添加子目录。添加的每个子目录也必须包含一个CMakeLists.txt文件作为该子目录的入口点。每个子目录的CMakeLists.txt文件被处理时,CMake在构建树中生成相应的目录作为默认的工作和输出目录。记住这一点非常关键,这样我们就可以使用外部构建了,而不必每次都使用蛋疼的内部构建,然后删除一堆文件才能从新构建。
2、<Script>
        一个单独的<script>.cmake源文件可以使用cmake命令行工具cmake -P <script>.cmake选项来执行脚本。脚本模式只是在给定的文件中运行命令,并且不生成构建系统。它不允许CMake命令定义或执行构建目标。
3、<Module>
       在Directory或Script中,CMake代码可以使用include()命令来加载.cmake。cmake内置了许多模块用来帮助我们构建工程,前边文章中提到的CheckFunctionExists。也可以提供自己的模块,并在CMAKE_MODULE_PATH变量中指定它们的位置。

(1)cmake基本编写格式:

举例:
add_executable(hello world.c foo.c) #这是一个注释
等于
add_executable(hello 
               world.c 
               foo.c)
#这是一个注释

       注意参数这一块,可以用引号包裹起来,这代表一个参数,假如一行不能写完,则用\\符号来表示连接成一行,也可以不用引号,但是假如参数带有分隔符,则会被认为是多个参数。

(2)定义变量

        定义变量常用的函数是set(KEY VALUE),取消定义变量是unset(KEY)。它们的值始终是string类型的,有些命令可能将字符串解释为其他类型的值。变量名是区分大小写的,可能包含任何文本,但是我们建议只使用字母数字字符加上_和-这样的名称。
        变量引用的形式为${variable_name},并在引用的参数或未引用的参数中进行判断。变量引用被变量的值替换,或者如果变量没有设置,则由空字符串替换。变量引用可以嵌套,并从内部进行替换,例如${outer_${inner_variable}veriable}。
       环境变量引用的形式为$ENV{VAR},并在相同的上下文中作为正常变量引用。

(3)cmake构建系统       

        这算是进入正文了。扯淡的介绍就不多讲了,直接干货。
        可执行文件和库是使用add_executable()和add_library()命令定义的。生成的二进制文件有合适的前缀、后缀和针对平台的扩展。二进制目标之间的依赖关系使用target_link_libraries()命令表示。

add_library(archive archive.cpp zip.cpp lzma.cpp)
add_executable(zipapp zipapp.cpp)
target_link_libraries(zipapp archive)

         在构建c程序的时候,因为要生成可执行文件,add_executable是必须的;构建安卓动态库的时候,add_library是必须的,因为jni需要调用动态库。

(4)外部构建 ※※

        前边提到过cmake的构建命令cmake .,也就是在当前目录构建工程,这样会生成一系列的缓存文件在当前目录,假如我们需要重新构建需要删除这些文件,其中CMakeCache.txt是必须删除的,否则不会构建最新的程序。
        看一下我们在工程根目录下执行cmake后是什么情况:

 ~/Desktop/Tutorial/Step1/ tree -L 1
.
├── CMakeCache.txt
├── CMakeFiles
├── CMakeLists.txt
├── Makefile
├── Tutorial
├── TutorialConfig.h
├── TutorialConfig.h.in
├── cmake_install.cmake
└── tutorial.cxx

        生成的文件与源文件交叉在一起,相当混乱。我们可以采用外部构建来分隔源文件与生成的文件,当我们需要清空缓存重新构建项目时,就可以删除这个文件夹下的所有内容,重新运行构建命令,保持源文件的整洁,从而更容易管理项目。
        首先新建一个文件夹build,这个文件夹就是我们用来存放生成的文件的目录,然后进入该目录,执行构建命令。

mkdir build # 创建build目录
cd build # 进入build目录
cmake .. # 因为程序入口构建文件在项目根目录下,采用相对路径上级目录来使用根目录下的构建文件

         此时可以看到生成的文件全部在build文件夹下了,构建完全没问题。以后的项目讲解中将全部使用外部构建。

~/Desktop/Tutorial/Step1/ tree -L 2
.
├── CMakeLists.txt
├── TutorialConfig.h.in
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Makefile
│   ├── TutorialConfig.h
│   └── cmake_install.cmake
└── tutorial.cxx
#为讲解一些基本指令编写的示例

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
message(STATUS ${PROJECT_NAME})
message(STATUS ${PROJECT_SOURCE_DIR})
message(STATUS ${PROJECT_BINARY_DIR})
message(STATUS ${Tutorial_SOURCE_DIR})
message(STATUS ${Tutorial_BINARY_DIR})
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)

# configure a header file to pass some of the CMake settings to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  )

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")

# add the executable
add_executable(Tutorial tutorial.cxx)

①message用法

   message类似于一个向控制台输出日志的工具,但是功能又稍微强大一些,在一些模式下能够终止程序构建。

message([<mode>] "message to display" ...)

②cmake_minimum_required (VERSION 2.6):

cmake_minimum_required (VERSION 2.6)

         为一个项目设置cmake的最低要求版本,并更新策略设置以匹配给定的版本。无论是构建项目还是构建库,都需要这个命令。 它的语法是这样的:

cmake_minimum_required(VERSION major.minor[.patch[.tweak]]
                       [FATAL_ERROR])

        版本号必须指定主次代号,后边的可选,请忽略可选项[FATAL_ERROR],完全没用。

        假如你指定的版本号大于你安装的cmake版本,将会停止构建并抛出一个错误:

CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
  CMake 3.11 or higher is required.  You are running version 3.10.2


-- Configuring incomplete, errors occurred!

   cmake_minimum_required必须在项目根目录下的最开始调用,也就是project()之前。在function()中调用该指令也可以,作用域将局限在函数内,但是必须以不影响全局使用为前提。

③ project (Tutorial)

           指定项目的名称为Tutorial,构建项目必须使用这个命令,构建库可以不指定。文档如下:

project(<PROJECT-NAME> [LANGUAGES] [<language-name>...])
project(<PROJECT-NAME>
        [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
        [DESCRIPTION <project-description-string>]
        [LANGUAGES <language-name>...])

        设置项目名称并将该名称存储在PROJECT_NAME变量中。同时也指定了四个变量:

PROJECT_SOURCE_DIR, <PROJECT_NAME>_SOURCE_DIR
PROJECT_BINARY_DIR, <PROJECT_NAME>_BINARY_DIR

        但是我们一般只使用前一个,这样更容易更改。在上边的代码中我们用message输出了这些变量的信息,执行构建命令后日志输出:

-- Tutorial
-- /Users/saka/Desktop/Tutorial/Step1
-- /Users/saka/Desktop/Tutorial/Step1/build   ## message(STATUS ${PROJECT_BINARY_DIR})
-- /Users/saka/Desktop/Tutorial/Step1
-- /Users/saka/Desktop/Tutorial/Step1/build

        我们也可以在指定项目名称时直接指定版本号,假如没有指定,则版本号为空。 版本号存储在下边几个变量中:

PROJECT_VERSION, <PROJECT-NAME>_VERSION
PROJECT_VERSION_MAJOR, <PROJECT-NAME>_VERSION_MAJOR
PROJECT_VERSION_MINOR, <PROJECT-NAME>_VERSION_MINOR
PROJECT_VERSION_PATCH, <PROJECT-NAME>_VERSION_PATCH
PROJECT_VERSION_TWEAK, <PROJECT-NAME>_VERSION_TWEAK

        通常我们推荐使用前一个。现在测试一下,在CMakeLists.txt文件中修改代码:

project (Tutorial
	VERSION 1.2.3
	DESCRIPTION "this is description"
	LANGUAGES CXX)
message(STATUS ${PROJECT_VERSION})
message(STATUS ${PROJECT_VERSION_MAJOR})
message(STATUS ${PROJECT_VERSION_MINOR})
message(STATUS ${PROJECT_VERSION_PATCH})
message(STATUS ${PROJECT_VERSION_TWEAK})
message(STATUS ${PROJECT_DESCRIPTION})
输出日志如下:
-- 1.2.3
-- 1
-- 2
-- 3
-- 
-- this is description

       在这设置版本号和用set设置版本号效果一样,取最后一次设置的值。由于我们没有指定tweak版本,所以为空,同时看到description被存储到PROJECT_DESCRIPTION这个变量中了。

        可以通过设置LANGUAGES来指定编程语言是C、CXX(即c++)或者Fortran等,如果没有设置此项,默认启用C和CXX。设置为NONE,或者只写LANGUAGES关键字而不写具体源语言,可以跳过启用任何语言。一般都是用cmake来编译c或者c++程序,所以用默认的就可以了。

configure_file 

   该命令的作用是复制文件到另一个地方并修改文件内容。语法如下:

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

           将input文件复制到output文件中,并在输入文件内容中替换@VAR@或${VAR}的变量值。每个变量引用将被替换为变量的当前值,如果变量的值未被定义,则为空字符串。(VAR必须与cmakelist.txt中的变量保持一直,否则会生成注释)。

input文件的定义形式为:

#cmakedefine VAR ..

经过configure后生成的文件内容被替换为:

#define VAR ...  //替换成功
/* #undef VAR */ //未定义的变量

        生成的文件将会保留在'#'与'cmakedefine'之间的空格和制表符。

       此处有一点需说明,现在clion默认使用cmake来构建程序,但是在clion中不支持cmakedefine关键字,所以可以直接使在input文件中填写#define VAR ...来编写宏定义,生成的结果与上边完全一样。clion有一个问题,就是直接用cmakedefine定义宏的时候假如#与cmakedefine之间有空格则不会替换cmakedefine为define,后边的变量会替换,但是不能编译成功,所以假如在clion中使用,要注意这几点,直接使用#define或者#cmakedefine,尽量不要加空格。

       介绍其中的选项: input和output假如不指定绝对路径,则会被默认设置为CMAKE_CURRENT_SOURCE_DIR和CMAKE_CURRENT_BINARY_DIR,也就是项目根目录和构建的目录;
       COPYONLY则只是复制文件,不替换任何东西,不能和NEWLINE_STYLE <style>一起使用。
       ESCAPE_QUOTES禁止为"转义。这个很蛋疼,不加这个命令的话假如变量中有a\"b,则在生成的文件中会直接使用转义后的字符a"b,加上指令后则按原来的文字显示a\"b;
       @ONLY只允许替换@VAR@包裹的变量${VAR}则不会被替换;
       NEWLINE_STYLE <style>设置换行符格式。

      举例: foo.h.in文件如下

#cmakedefine FOO_ENABLE
#cmakedefine FOO_STRING "@FOO_STRING@"

      CMakeLists.txt中添加代码来设置一个开关,下边会执行if中的语句:

option(FOO_ENABLE "Enable Foo" ON)
if(FOO_ENABLE)
  set(FOO_STRING "foo")
endif()
configure_file(foo.h.in foo.h @ONLY)

    生成的文件foo.h:

#define FOO_ENABLE
#define FOO_STRING "foo"

   假如设置为off,option(FOO_ENABLE "Enable Foo" OFF),则不会执行if中的语句,生成的文件如下:

/* #undef FOO_ENABLE */
/* #undef FOO_STRING */

⑤include_directories这一行:include_directories("${PROJECT_BINARY_DIR}")

    这句话的意思将当前的二进制目录添加到编译器搜索include目录中,这样就可以直接使用上一步生成的头文件了。

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

        将给定的目录添加到编译器用来搜索包含文件的目录。相对路径为相对于当前根目录。
        括号中的目录被添加到当前CMakeLists文件的INCLUDE_DIRECTORIES目录属性中。它们也被添加到当前CMakeLists文件中的每个目标的INCLUDE_DIRECTORIES目标属性中。

        默认情况下,指定的目录被追加到当前的include目录列表中。通过将CMAKE_INCLUDE_DIRECTORIES_BEFORE设置为ON,可以更改此默认行为。通过明确使用AFTER或BEFORE,您可以选择添加和预先设置。如果给出SYSTEM选项,那么编译器会被告知这些目录在某些平台上是指系统包含的目录。

(5)CMake 链接第三方的库 ※(指定支持C++11)

举例 (1)链接libev, 如下:

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

#如何支持C++11呢? 在版本要求的下面, 加上这两句话就行
SET(CMAKE_C_COMPILER g++)
add_compile_options(-std=c++11)

# 项目信息
project (server)

# 查找当前目录下的所有源文件,并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 添加第三方的库
set(INC_DIR /usr/local/include/)  #用全路径
set(LINK_DIR /usr/local/lib)      #用全路径

include_directories(${INC_DIR})
link_directories(${LINK_DIR})
link_libraries(ev)


# 指定生成目标
add_executable(server ${DIR_SRCS})

# 将第三方的库链接到可执行文件
target_link_libraries(server ev)

举例(2)导入第三方库wfdb库:

导入第三方库的具体步骤:
       CMake的配置信息写在了CMakeList.txt文件中。在CMakeList.txt文件里,我们首先定义两个变量INC_DIR和LINK_DIR,用来表示头文件路径和库的路径。这里以我放在Downloads文件下的wfdb库为例,代码如下:

set(INC_DIR /Users/haoran/Downloads/wfdb/include)
set(LINK_DIR /Users/haoran/Downloads/wfdb/lib)

然后依次设置头文件目录、库目录、要链接的库,如下:

include_directories(${INC_DIR})
link_directories(${LINK_DIR})
link_libraries(wfdb)

 注意以上代码须放在add_executable语句之前,而接下来的链接库操作则须放在add_executable语句之后。

使用如下语句完成库的链接操作:

target_link_libraries(wfdb_demo wfdb)

 括号中的wfdb_demo为工程名称,wfdb为库的名称。至此我们就完成第三方库的链接过程。

此工程完整的CMake代码如下:
cmake_minimum_required(VERSION 3.6)
project(wfdb_demo)
set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp)

set(INC_DIR /Users/haoran/Downloads/wfdb/include)
set(LINK_DIR /Users/haoran/Downloads/wfdb/lib)
include_directories(${INC_DIR})
link_directories(${LINK_DIR})
link_libraries(wfdb)

add_executable(wfdb_demo ${SOURCE_FILES})
target_link_libraries(wfdb_demo wfdb)

(6)cmake:用add_subdirectory()添加外部项目文件夹

        一般情况下,我们的项目各个子项目都在一个总的项目根目录下,但有的时候,我们需要使用外部的文件夹,怎么办呢? add_subdirectory命令,可以将指定的文件夹加到build任务列表中。下面是将与当前项目平级的一个目录下的子目录用add_subdirectory命令加进来的CMakelists.txt脚本片段 :

#定义CASSDK位置
if(NOT CASSDK_DIR)
    set( CASSDK_DIR ${CMAKE_SOURCE_DIR}/../cassdk)
endif() 

if( IS_DIRECTORY ${CASSDK_DIR} )
    add_subdirectory( ${CASSDK_DIR}/cassdk )
else() 
    message(FATAL_ERROR "INVALID FOLDER 'CASSDK_DIR'=${CASSDK_DIR}" ) 
endif()

然后执行CMakeList.txt脚本时报错了:

CMake Error at CMakeLists.txt:35 (add_subdirectory): 
add_subdirectory not given a binary directory but the given source 
directory “J:/workspace/cassdk/cassdk” is not a subdirectory of 
“J:/workspace/codemgr”. When specifying an out-of-tree source a binary 
directory must be explicitly specified.

 报错原因也很明确,因为要添加的这个文件夹不是当前项目的子目录。最后一句指明了方向:要指定一个外部的文件夹必须显式指定a binary directory。

        原来add_subdirectory还有一个 binary_dir参数(一般这个参数用不到,所以从来没关注过),这个参数用来指定source_dir在输出文件夹中的位置,如果没有指定的时候,就用source_dir的值。 如果要添加外部文件夹,binary_dir就必须指定。所以上面的代码修改如下:

#定义CASSDK位置
if(NOT CASSDK_DIR)
    set( CASSDK_DIR ${CMAKE_SOURCE_DIR}/../cassdk)
endif() 

if( IS_DIRECTORY ${CASSDK_DIR} ) # 第二个cassdk.out参数用于指定外部文件夹在输出文件夹中的位置 
    add_subdirectory( ${CASSDK_DIR}/cassdk cassdk.out)
else() 
    message(FATAL_ERROR "INVALID FOLDER 'CASSDK_DIR'=${CASSDK_DIR}" ) 
endif()

//参考链接cmake:用add_subdirectory()添加外部项目文件夹_weixin_33755649的博客-CSDN博客

  ① INCLUDE_DIRECTORIES(添加头文件目录)

         它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用(这里特指c++。c和Java中用法类似)。比如:

include_directories("/opt/MATLAB/R2012a/extern/include")
export CPLUS_INCLUDE_PATH=CPLUS_INCLUDE_PATH:$MATLAB/extern/include
语法:
link_directories(directory1 directory2 ...)

        它相当于g++命令的-L选项的作用,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。比如:

LINK_DIRECTORIES("/opt/MATLAB/R2012a/bin/glnxa64")
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MATLAB/bin/glnxa64

    List of direct link dependencies. 

比如:
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

也可以写成:
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")
语法:TARGET_LINK_LIBRARIES(targetlibrary1 <debug | optimized> library2 ..)
比如(以下写法都可以): 
TARGET_LINK_LIBRARIES(myProject hello),连接libhello.so库
TARGET_LINK_LIBRARIES(myProject libhello.a)
TARGET_LINK_LIBRARIES(myProject libhello.so)
再如:
TARGET_LINK_LIBRARIES(myProject libeng.so)  #这些库名写法都可以。
TARGET_LINK_LIBRARIES(myProject eng)
TARGET_LINK_LIBRARIES(myProject -leng)

  ⑤联合示例: 

以下CMakeLists.txt效果相当,在ubuntu 12.04 + g++4.6下测试编译通过:

<示例 - 1>
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)  
include_directories("/opt/MATLAB/R2012a/extern/include")  
  
#directly link to the libraries.  
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")  ## 全路径
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")   ## 全路径
#equals to below  
#LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")  
  
add_executable(myProject main.cpp) 
<示例 - 2>
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)  
include_directories("/opt/MATLAB/R2012a/extern/include")  
  
LINK_DIRECTORIES("/opt/MATLAB/R2012a/bin/glnxa64")  ## 全路径
  
add_executable(myProject main.cpp)  
  
target_link_libraries(myProject eng mx)  
#equals to below  
#target_link_libraries(myProject -leng -lmx)  
#target_link_libraries(myProject libeng.so libmx.so)  

 【CMakeList.txt的简单实战】

<1>CMake 简介

         CMake 是一个跨平台的自动化建构系统,它使用一个名为 CMakeLists.txt 的文件来描述构建过程,可以产生标准的构建文件,如 Unix 的 Makefile 或Windows Visual C++ 的 projects/workspaces 。文件 CMakeLists.txt 需要手工编写,也可以通过编写脚本进行半自动的生成。CMake 提供了比 autoconfig 更简洁的语法。在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:
1)编写 CmakeLists.txt。
2)执行命令“cmake PATH”或者“ccmake PATH”生成 Makefile ( PATH 是 CMakeLists.txt所在的目录 )。
3)使用 make 命令进行编译。

<工程练习 - 1>

源代码分布情况:假设我们的项目中只有一个源文件 main.cpp

./eg_demo/main.cpp

源文件main.cpp内容:

#include <iostream>
int main()
{
    std::cout<<"Hello world"<<std::endl;
    return 0;
}

注:为了构建该项目,我们需要编写文件 CMakeLists.txt 并将其与 main.cpp 放在 同一个目录下。
CMakeLists.txt内容为:

PROJECT(Hello)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_EXECUTABLE(main ${DIR_SRCS})

       ※ CMakeLists.txt 的语法比较简单,由命令、注释和空格组成,其中命令是不区分大小写的,符号"#"后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。

       例如对于上面清单2的 CMakeLists.txt 文件:第一行是一条命令,名称是 PROJECT ,参数是 Hello,该命令表示项目的名称是 Hello 。第二行的命令限定了 CMake 的版本。第三行使用命令 AUX_SOURCE_DIRECTORY 将当前目录中的源文件名称赋值给变量 DIR_SRCS 。 CMake 手册中对命令 AUX_SOURCE_DIRECTORY 的描述如下:aux_source_directory(<dir> <variable>)该命令会把参数 <dir>中所有的源文件名称赋值给参数<variable>。 第四行使用命令 ADD_EXECUTABLE 指示变量 DIR_SRCS 中的源文件需要编译 成一个名称为 main 的可执行文件。

       CMake的编译基本就两个步骤:
       cmake 指向CMakeLists.txt所在的目录,例如cmake ..  表示CMakeLists.txt在当前目录的上一级目录。cmake后会生成很多编译的中间文件以及makefile文件,所以一般建议新建一个新的目录,专门用来编译,例如:

mkdir build
cd build
cmake ..  #步骤1
make      #步骤2

      make根据生成makefile文件,编译程序。

      camke 的运行结果:

[eg_demo]$ mkdir build
[eg_demo]$ cd build/
[build]$ 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
-- Configuring done
-- Generating done
-- Build files have been written to: /eg_demo/build

[build]$ make
make: Warning: File `Makefile' has modification time 969 s in the future
make[1]: Warning: File `CMakeFiles/Makefile2' has modification time 969 s in the future
make[2]: Warning: File `CMakeFiles/main.dir/flags.make' has modification time 969 s in the future
Scanning dependencies of target main
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[2]: Warning: File `CMakeFiles/main.dir/flags.make' has modification time 969 s in the future
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable main
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
[100%] Built target main
make[1]: warning:  Clock skew detected.  Your build may be incomplete.
make: warning:  Clock skew detected.  Your build may be incomplete.

[build]$ ./main
Hello world

<工程练习 - 2>

源代码分布情况:

./eg_demo/main.cpp 、test.cpp 、test.h

主函数main.cpp:

#include <iostream>
#include "test.h"
int main()
{
    std::cout<<"Hello world"<<std::endl;
	print_test();
    return 0;
}

test.cpp内容:

#include "test.h"
void print_test()
{
	std::cout<< "src:test"<<std::endl;
}

test.h中内容:

#include <iostream>
void print_test();

CMakeLists.txt内容:(与工程练习 - 1一致)

PROJECT(Hello)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_EXECUTABLE(main ${DIR_SRCS})

<工程练习 - 3>

源代码分布情况:

./eg_demo/main.cpp
./eg_demo/src/test.cpp 、test.h

程序中的内容和第二个项目一致。
多目录工程的CmakeLists.txt编写
——主文件(eg_demo)的CMakeLists.txt:

PROJECT(Hello)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

INCLUDE_DIRECTORIES(./ ./src)
ADD_SUBDIRECTORY(src)

AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_EXECUTABLE(main ${DIR_SRCS})

TARGET_LINK_LIBRARIES(main test)

——子文件(src)的CMakeLists.txt:

AUX_SOURCE_DIRECTORY(. DIR_TEST_SRCS)
ADD_LIBRARY(test ${DIR_TEST_SRCS})

  camke 的运行结果:(注:将test修改为mytest,可消除 Policy CMP0037 告警)

 mkdir build
[eg_demo3]$ cd build
[build]$ 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
CMake Warning (dev) at src/CMakeLists.txt:2 (ADD_LIBRARY):
  Policy CMP0037 is not set: Target names should not be reserved and should
  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
  details.  Use the cmake_policy command to set the policy and suppress this
  warning.

  The target name "test" is reserved or not valid for certain CMake features,
  such as generator expressions, and may result in undefined behavior.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring done
-- Generating done
-- Build files have been written to: /eg_demo3/build
[build]$ make
make: Warning: File `Makefile' has modification time 937 s in the future
make[1]: Warning: File `CMakeFiles/Makefile2' has modification time 938 s in the future
make[2]: Warning: File `src/CMakeFiles/test.dir/flags.make' has modification time 937 s in the future
Scanning dependencies of target test
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[2]: Warning: File `src/CMakeFiles/test.dir/flags.make' has modification time 937 s in the future
[ 25%] Building CXX object src/CMakeFiles/test.dir/test.cpp.o
[ 50%] Linking CXX static library libtest.a
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
[ 50%] Built target test
make[2]: Warning: File `CMakeFiles/main.dir/flags.make' has modification time 934 s in the future
Scanning dependencies of target main
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[2]: Warning: File `CMakeFiles/main.dir/flags.make' has modification time 934 s in the future
[ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.o
[100%] Linking CXX executable main
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
[100%] Built target main
make[1]: warning:  Clock skew detected.  Your build may be incomplete.
make: warning:  Clock skew detected.  Your build may be incomplete.
[build]$ ./main
Hello world
src:test

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值