CMake之简单工程实践
来源:互联网 发布:怎么查看淘宝积分 编辑:程序博客网 时间:2024/06/05 06:04
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之简单工程实践
- 一个简单的CMake工程示例
- CMAKE之配置windows驱动工程---VS2008
- Cmake 实践
- CMake实践
- Cmake实践
- cmake实践
- 用CMake写一个简单的交叉编译测试工程
- 用CMake写一个简单的交叉编译测试工程
- 一些简单的安全加密工程实践
- C语言工程实践-简单文本编辑器
- linux下cmake编译C++工程之总结篇
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- OpenCV基础篇之使用CMake管理工程
- JAVA设计模式(享元模式)
- 原型链的从对象创建到原理详解
- 关于view的drawRect多次被调用出现绘图重叠问题
- Linux Select
- 计算机程序的思维逻辑 (1) - 数据和变量
- CMake之简单工程实践
- HOF特征
- oracle插入日期to_date转换函数
- 多渠道共存打包(二)
- mysql group replication集群搭建
- Zabbix, Nagios告警规则比较
- 布局文件的NullPointerException
- 【python】couchbase稽核脚本
- 【转载】HTML的新标签template