天天看点

【整理】CMake 介绍和 CMake 实践

【cmake 优点】:

开放源代码,使用 bsd 许可证发布。

跨平台,可以生成 native 编译配置文件。在 linux/unix 平台可以生成 makefile,在 mac 平台可以生成 xcode,在 windows 平台可以生成 msvc 工程的配置文件。

能够管理大型项目。

简化编译构建过程和编译过程,只需要 cmake + make 就可以。

高效率。

可扩展,可以为 cmake 编写特定功能的模块,扩充 cmake 功能。

【如何安装 cmake】:

1. cmake 的安装可以使用 autotools 进行安装,点击cmake-2.8.6.tar.gz链接,可以对软件进行下

2. 执行 ./configure; make; make install

【cmake的原理】 

准备main.cpp文件

<a href="http://my.oschina.net/moooofly/blog/89722#">?</a>

1

2

3

4

5

6

7

8

9

<code>//main.cpp</code>

<code>#include&lt;cstdio&gt;</code>

<code>int</code> <code>main()</code>

<code>{</code>

<code>    </code><code>printf</code><code>(</code><code>"hello world from main\n"</code><code>);</code>

<code>    </code><code>return</code> <code>0;</code>

<code>}</code>

a.创建 cmakelists.txt(注意:此文件名大小写必须如此命名),向该文件中加入以下几行(内容中命令的大小写无所谓):

<code>project (hello)</code>

<code>set(src_list main.cpp)</code>

<code>message(status</code><code>"this is binary dir "</code> <code>${hello_binary_dir})</code>

<code>message(status</code><code>"this is source dir "</code><code>${hello_source_dir})</code>

<code>add_executable(hello ${src_list})</code>

b.运行以下命令(linux下):

<code>$ cmake .                (别忘记加上这个点,表示当前目录)</code>

【整理】CMake 介绍和 CMake 实践

执行完该命令后执行ls可以看到:

【整理】CMake 介绍和 CMake 实践

生成了cmakefiles(目录)、cmakecache.txt、cmake_install.cmake以及makefile文件。

c.执行make。

【整理】CMake 介绍和 CMake 实践

这时当前目录下就会生成可执行文件:

【整理】CMake 介绍和 CMake 实践

【例子解释】:

上面cmakelists.txt的内容重新列出如下: 

project指令的语法:

project(projectname [cxx] [c] [java]) 

该指令用来定义工程名称和工程支持的语言。这个指令也同时隐式定义了两个cmake变量:&lt;projectname&gt;_binary_dir以及&lt;projectname&gt;_source_dir。

在该例子中就是hello_binary_dir和hello_source_dir,两个变量指的都是当前工程的路径。 

set指令的语法:

set(var[value] [cache type docstring [force]]) 

set指令是用来显式的定义变量的,我们之前用到的是set(src_list main.cpp),如果有多个源文件,也可以定义成set(src_list main.cpp t1.cpp t2.cpp)。 

message指令的语法是:

message([send_error | status | fatal_error] "message to display" ...) 

这个指令用于向终端输出用户信息,包含三种类型:

send_error,产生错误,生成过程被跳过。

satus,输出前缀为-的信息。

fatal_error,立即终止所有cmake过程。 

上例使用的是status类型进行信息输出,用于显示由project指令隐式定义的两个变量hello_binary_dir和hello_source_dir的值。 

add_executable(hello ${src_list})

定义了这个,工程会生成一个文件名为hello的可执行文件,相关的源文件是src_list中定义的源文件列表,本例中你可以直接写成add_executable(hello main.c)。

本例cmakelists.txt的最简化形式:

<code>project(hello)</code>

<code>add_executable(hello main.c)</code>

=== 我是分割线 ===

下面我们介绍一个比较实用的例子,既包含生成静态库又包含引入外部头文件和链接库的cmake demo。

先按照工程规范建立工程目录并编写代码,以下面的工程目录为例进行解释这个例子,工程的目录结构为:

【整理】CMake 介绍和 CMake 实践

编译工程要实现的目标:

添加子目录doc,用以放置这个工程的文档hello.txt。

生成hello的静态库,并在main可执行程序链接hello静态库。

在这个工程中添加copyright和readme文件。

在工程目录中添加一个run.sh的脚本,用以调用生成的二进制可执行文件。

将生成的二进制文件生成到bin子目录中。

编写安装程序。 

1. 编写cmakelists.txt

      由于一个工程目录中包含多个项目,其中在此项目中包含util项目和main项目,其中util项目是用以生成main程序需要的静态库,main是用以生成可执行文件。

      在整个工程项目的根目录下的cmakelists.txt是用来定义工程需要的cmake设置以及子目录src,用以递归调用src中的makelists.txt。该cmakelists.txt的内容定义如下: 

<code>add_subdirectory(src)</code>

      目录src中的cmakelists.txt用以定义src目录下包含的两个工程(main和util)的依赖关系。

      目录util里面的cmakelists.txt是用以定义生成util静态库的规则,其中内容如下:

<code>set(library_output_path ${hello_source_dir}</code><code>/lib</code><code>)</code>

<code>set(cmake_c_compiler g++)</code>

<code>set(src_list hello.c)</code>

<code>include_directories(${hello_source_dir}</code><code>/include</code><code>)</code>

<code>add_library(util static ${src_list})</code>

set(library_output_path ${hello_source_dir}/lib) -- 定义了库生成的路径,内部变量library_output_path用于存放库的生成路径。 

set(cmake_c_compiler g++) -- 定义c的编译器为g++,防止出现c和c++代码在不指定c编译器的情况下默认使用gcc,导致系统编译混乱。 

set(src_list hello.c) -- 定义库文件需要的源文件。

include_directories(${hello_source_dir}/include) -- 定义非标准库头文件要搜索的路径。 

其中include_directories命令的格式为:

include_directories([after|before] [system] dir1 dir2 ...)

add_library(util static ${src_list}) -- 定义生成库的名字、类型和库所需要的源文件,

其中add_library命令格式为:

add_library(libname [shared|static|module] [exclude_from_all]

source1 source2 ... sourcen)

      目录main里面的cmakelists.txt是用来定义可执行程序编译和链接时所需要的一些命令或环境。内容如下: 

<code>set(executable_output_path ${hello_source_dir}</code><code>/bin</code><code>)</code>

<code>link_directories(${hello_source_dir}</code><code>/lib</code><code>)</code>

<code>target_link_libraries(hello util)</code>

include_directories(${hello_source_dir}/include) -- 定义工程引用的include文件夹位置,其中存放使用到的库的头文件。

link_directories(${hello_source_dir}/lib) -- 定义工程引用的库文件位置,其中存放着库文件。

add_executable(hello ${src_list}) -- 定义生成的可执行文件。

target_link_libraries(hello util) -- 用以定义链接时需要的库文件。 

2.在工程目录下创建build目录,并采用out-of-source方式编译项目。执行命令

<code>$ cmake ..</code>

执行结果如下

【整理】CMake 介绍和 CMake 实践

执行tree命令,这时在build目录下生成了中间编译文件:

<code>$ tree .</code>

【整理】CMake 介绍和 CMake 实践

执行make命令,结果如下:

【整理】CMake 介绍和 CMake 实践

可以看到工程创建和编译成功了。 

3. 安装

      在工程目录下添加copyright、readme和run.sh,重新编辑工程目录下的cmakelists.txt。在cmakelists.txt中添加如下命令: 

<code>install(files copyright readme destination share</code><code>/doc/cmake_demo</code><code>)</code>

<code>install(programs run.sh destination bin)</code>

<code>install(programs bin</code><code>/hello</code> <code>destination bin)</code>

<code>install(directory doc/ destination share</code><code>/doc/cmake_demo</code><code>)</code>

      这些命令表示在执行make install命令时,安装程序会拷贝相应的文件、目录或程序到指定的前缀开始的目录中,cmake执行命令如下: 

<code>cmake -dcmake_install_prefix=~</code><code>/data/cmake_demo</code> <code>..</code>

      这时将工程目录安装到~/data/cmake_demo目录下。执行结果如下:

【整理】CMake 介绍和 CMake 实践

其中cmake编译c、c++工程完毕。