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


0 0