`
844604778
  • 浏览: 551276 次
文章分类
社区版块
存档分类
最新评论

CMake之简单工程实践

 
阅读更多

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实践.pdf

    CMake实践是大神总结的CMake的使用用法,涵盖了CMake的所有使用方式,本人更是进一步添加了书签,是你能够快速定位到你需要的知识,本PDF为高清版+书签,学习CMake的同学可以下载。 PS:非常好的学习资料,我看完...

    cmake创建多工程例子

    cmake创建多工程例子的简单例子

    cmake教程,cmake实践,跟我一起写Makefile,三本合一带书签

    cmake教程,cmake实践,跟我一起写Makefile三本合一,带书签。 学习cmake很好的教材

    CMake实践 中文翻译版

    一份“面向使用和实用”的cmake文档,也就是本教程《cmake实践》(Cmake Practice)

    cmake实践_cmake_

    CMake实战主要讲解如何利用cmake工具在服务器领域构建c/c++工程,当然在不同平台上的很多工具都用cmake构建,熟悉掌握cmake的使用,可以更深入的了解代码编译深层的东西

    cmake实践.pdf

    Cmake实践.pdf,Cmake实践.pdfCmake实践.pdf,欢迎大家下载。

    使用vscode cmake插件构建的CMake工程模板

    使用vscode cmake插件构建的CMake工程模板

    cmake简单工程例子

    一个简单的cmake工程例子,教你你如何使用camek创建一个qt工程.构建CMakeLists的基本工作 通过CMakeLists.txt简单构建了一个项目,说明了构建一个项目要设置的内容,例如确定最低版本、设置项目名字、设置包含路径等...

    cmake多目录工程实现

    工程内存在多个文件夹的cmake的编写,代码部分摘录字cisco的SIP协议栈

    Cmake实践.pdf

    Cmake实践.pdf

    Cmake实践

    CMAKE实践

    cmake教程 + cmake 实践(中文)

    整理了一下 放在一起 通俗易懂 中文 其实里面 两个都有实例

    C++通过CMake构建QT 5.12的工程模板

    这是在ubuntu16.04系统下,用C++通过cmake构建qt5.12的工程模板。 自动根据.ui文件生成.h和cpp文件,利用qtcreator修改.ui文件后,无需其他设置,直接make可生成修改后的界面。 使用方法一:按照普通的cmake工程...

    cmake实践,学习cmake的一本好书

    CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档...

    cmake构建msvc工程示例

    cmake构建sln及工程文件的简单示例。附原始工程文件和cmakelist.txt。示例中配置工程包含头文件源文件资源文件,及编译选项的方法。示例中只配置了release x64版本。未对复杂目录结构进行说明,有兴趣可参考官方文档...

    cmake实践教程&语法简介

    cmake实践教程.pdf cmake语法简介.pdf

    cmake demo,用于生成简单的cmake工程,工程包括生成动态库和链接动态库的demo和test工程

    cmake demo,用于生成简单的cmake工程,工程包括生成动态库和链接动态库的demo和test工程

    cmake完整工程示例

    1. 完整cmake示例,多晚文件管理 2. 演示如何生成动态库,以及如何使用动态库

    cmake实践

    开始工程比较小,一直手写makefile来管理工程,随着代码量的增加,工程的管理也越来越麻烦。而autotools,上手显得相对比较麻烦,选择了使用cmake来管理工程。

Global site tag (gtag.js) - Google Analytics