CMake之简单工程实践
转载请说明出处:http://blog.csdn.net/cywosp/article/details/9763261
在实践CMake之前先让我们来看看cmake是什么,下面是从百度百科上摘抄下来的关于cmake的简介:
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CmakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是
CMake 和 SCons 等其他类似系统的区别之处。
CMake 可以编译源代码、制作程式库、产生适配器(wrapper)、还可以用任意的顺序建构执行档。CMake 支援 in-place 建构(二进档和源代码在同一个目录树中)和 out-of-place 建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake 也支持静态与动态程式库的建构。
“CMake”这个名字是“cross platform make”的缩写。虽然名字中含有“make”,但是CMake和Unix上常见的“make”系统是分开的,而且更为高阶。
从上面可知CMake是一个跨平台的编译规则的生成工具,在不同平台上生成不同的编译规则文件,然后我们就可以根据这些文件来编译我们程序了。比 如Linux中生成makefile,Windows中生成project文件。我们都知道当我们的项目非常大时,自己去编写makefile似乎有点繁琐,但是编写CMake相关文件却是非常简单的。下面举几个例子来看看到底有多简单。(本文只举在linux系统中的例子)
1. 首先我们有个简单的程序放在/mnt/test目录中,目录中有一个main.cpp文件,代码如下:
//main.cpp
#include <iostream>
using namespace std;
int main (int argc, char* argv[])
{
cout << "Hello World!" << endl;
return 0;
}
现在让我们来编写一个CMake中必不可少的名为CMakeLists.txt文件:
#设置cmake的版本号和向下兼容性,这个是根据系统安装的cmake来确定的,而且这个是一定不能少的,否则就会报错误
cmake_minimum_required (VERSION 2.8)
cmake_policy (VERSION 2.8)
#设置工程的名字
project (hello)
#将当前目录路径作为源文件所在目录,并把该路径存入变量SRC_LIST中。cmake会在${SRC_LIST}目录中查找相关可以被编译源文件和头文件
#加入到工程中
aux_source_directory (. SRC_LIST)
#通过此来决定最终的生成的可执行文件名,以及生成该所需要的源文件。其中PROJECT_NAME变量是上面project中的名字,它是一个当前工程
#全局变量。SRC_LIST是上面定义的变量
add_executable (${PROJECT_NAME} ${SRC_LIST})
以上就是一个非常简单的CMakeLists.txt文件了,现在让我们来编译该工程。进入工程所在目录
cd /mnt/test
先生成makefile文件
cmake . #.代码当前目录,你也可以cmake /mnt/test
命令完成之后在当前目录会生成如下几个文件和目录:
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
到此我们就得到了最熟悉的MakeFile文件了。当然你会发现突然在工程目录中多了几个文件让工程目录很乱,这让人很不爽。我们可以在系统的任何
地方创建一个目录然后进入到该目录中执行cmake /mnt/test,这样临时生成的文件就都在该目录下了。为了简单起见本例中在/mnt/test目录中建了
一个build目录。
mkdir /mnt/test/build
cd /mnt/test/build
cmake /mnt/test
make
这样我们得到了一个名为hello的可执行文件。当然当前编译的程序是Debug版的,如果我们想编译成Release版的我们可以这样做:
cmake -DCMAKE_BUILD_TYPE=Release /mnt/test#同时也可以将Release改成Debug
2. 下面我们在来看一个头文件和源文件分离的例子,其目录结构如下:
/mnt/test2
|____src
| |__________Car.cpp
|____include
| |__________Car.h
|____main.cpp
|____build
|___________CMakeLists.txt
//Car.h:
#include <iostream>
class Car
{
public:
Car ();
~Car ();
};
//Car.cpp
#include "Car.h"
Car::Car ()
{
std::cout << "Constructor" << std::endl;
}
Car::~Car ()
{
std::cout << "Deconstructor" << std::endl;
}
//main.cpp
#include <iostream>
#include "Car.h"
int main (int argc, char* argv[])
{
Car c;
return 0;
}
#CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
cmake_policy (VERSION 2.8)
project (car)
#将头文件的目录包含到工程中
include_directories (../include)
#将当前目录加入工程中
aux_source_directory (../ PROJECT_ROOT)
#将源文件加入工程中
aux_source_directory (../src SRC)
add_executable (${PROJECT_NAME} ${PROJECT_ROOT} ${SRC})
3. 下面来看一个编译成库文件的例子,目录结构如下
/mnt/test3
|_____libsrc
| |____lib
| |____include
| | |________Car.h
| |____src
| | |________Car.cpp
| |_____build
| |________CMakeLists.txt
|_____build
| |_____CMakeLists.txt
|_____main.cpp
其中Car.h和Car.cpp、main.cpp与例2中的一样,变化的是两个CMakeLists.txt
#/mnt/test3/libsrc/build/CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
cmake_policy (VERSION 2.8)
project (car)
#将头文件的目录包含到工程中
include_directories (../include)
#将当前目录加入工程中
aux_source_directory (.. PROJECT_ROOT)
#将源文件加入工程中
aux_source_directory (../src SRC)
#设置库生成后存放的路劲,LIBRARY_OUTPUT_PATH一定要大写不然不生效
set (LIBRARY_OUTPUT_PATH "../lib/")
#将工程编译成一个动态库(libcar.so),SHARED标志生成动态库,STATIC标志生成静态库
add_library (${PROJECT_NAME} SHARED ${PROJECT_ROOT} ${SRC})
#/mnt/test3/build/CMakeLists.txt
#这里与之前的稍微有点变化——版本号改成了2.8.1。因为在2.8.1之前的版本中link_directories是需要绝对路径的而不能像一下的那样写
cmake_minimum_required (VERSION 2.8.1)
cmake_policy (VERSION 2.8.1)
project (test3)
include_directories (../libsrc/include)
aux_source_directory (../ PROJECT_ROOT)
#将要链接的库所在的路劲加入工程,在上面我们将库编译好后放在了/mnt/test3/libsrc/lib目录中
link_directories ("../libsrc/lib")
add_executable (${PROJECT_NAME} ${PROJECT_ROOT})
#设置工程所生成的目标文件所需要的链接的库,在这里我们需要libcar.so这个库
target_link_libraries (${PROJECT_NAME} car)
在准备好上述文件之后,我们来编译整个程序。首先先编译库进入/mnt/test3/build目录中直接执行cmake . && make即可,然后到/mnt/test3/build中同样执行cmake . && make
4. 到此为止一些简单的工程我们已经能够轻松应付了,以下还有一些写CMakeLists.txt比较常用的:
link_libraries #设置编译时要连接的库名
假如我们的工程里需要连接数学库和线程库我们可以如下编写,库名之间用空格隔开:link_libraries (m pthread)
add_definitions #设置编译选项
有时候我们编译工程需要在gcc或者g++中加入以下编译选选项,在此我们可以这样做(选项之间用空格隔开)比如:
add_definitions ("-g -DYOU_DEFINITION") #-g编译成可调试的程序,YOU_DEFINITION是程序中使用到的宏需要在其之前加上-D
#设置编译好的可执行文件在执行时连接库的路径
set (CMAKE_INSTALL_RPATH .;/usr/local/lib64)
set (CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
add_subdirectory #将工程中的子目录加入编译工程中
假如CMakeLists.txt所在目录下有个test目录,test目录中也有一个CMakeLists.txt文件那么我们就可以直接将test目录加入。这在模块编程中很有用:
add_subdirectory (test)
本文对CMake只做简单的工程讲解,其是一个非常强大的工具,可以减少很多我们在开发工程中所遇到的繁杂的问题。网上有很多相关图书和Bolg而且也有很多的开源项目使用了CMake作为编译,有兴趣的可以继续深入。
注:在工程开发中为了有所区别大多数编写CMakeLists.txt的时候都采用大写字母。
更多可参考:http://www.cmake.org/cmake/help/cmake_tutorial.html
其对应的中文:http://www.cnblogs.com/coderfenghc/archive/2013/01/20/2846621.html
分享到:
相关推荐
CMake实践是大神总结的CMake的使用用法,涵盖了CMake的所有使用方式,本人更是进一步添加了书签,是你能够快速定位到你需要的知识,本PDF为高清版+书签,学习CMake的同学可以下载。 PS:非常好的学习资料,我看完...
cmake创建多工程例子的简单例子
cmake教程,cmake实践,跟我一起写Makefile三本合一,带书签。 学习cmake很好的教材
一份“面向使用和实用”的cmake文档,也就是本教程《cmake实践》(Cmake Practice)
CMake实战主要讲解如何利用cmake工具在服务器领域构建c/c++工程,当然在不同平台上的很多工具都用cmake构建,熟悉掌握cmake的使用,可以更深入的了解代码编译深层的东西
Cmake实践.pdf,Cmake实践.pdfCmake实践.pdf,欢迎大家下载。
使用vscode cmake插件构建的CMake工程模板
一个简单的cmake工程例子,教你你如何使用camek创建一个qt工程.构建CMakeLists的基本工作 通过CMakeLists.txt简单构建了一个项目,说明了构建一个项目要设置的内容,例如确定最低版本、设置项目名字、设置包含路径等...
工程内存在多个文件夹的cmake的编写,代码部分摘录字cisco的SIP协议栈
Cmake实践.pdf
CMAKE实践
整理了一下 放在一起 通俗易懂 中文 其实里面 两个都有实例
这是在ubuntu16.04系统下,用C++通过cmake构建qt5.12的工程模板。 自动根据.ui文件生成.h和cpp文件,利用qtcreator修改.ui文件后,无需其他设置,直接make可生成修改后的界面。 使用方法一:按照普通的cmake工程...
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档...
cmake构建sln及工程文件的简单示例。附原始工程文件和cmakelist.txt。示例中配置工程包含头文件源文件资源文件,及编译选项的方法。示例中只配置了release x64版本。未对复杂目录结构进行说明,有兴趣可参考官方文档...
cmake实践教程.pdf cmake语法简介.pdf
cmake demo,用于生成简单的cmake工程,工程包括生成动态库和链接动态库的demo和test工程
1. 完整cmake示例,多晚文件管理 2. 演示如何生成动态库,以及如何使用动态库
开始工程比较小,一直手写makefile来管理工程,随着代码量的增加,工程的管理也越来越麻烦。而autotools,上手显得相对比较麻烦,选择了使用cmake来管理工程。