伙伴云客服论坛»论坛 S区 S软件开发 查看内容

0 评论

0 收藏

分享

零根底学习cmake系统

目录

    什么是cmake入门理论
      构建单个源文件同一个目录,多个源文件多个目录多个源文件自定义编译选项
    最后


什么是cmake



根据其官网的定义,cmake是一个开源跨平台的,用于构建、测试和打包软件的一个套件工具。与cmake相关的几个概念需要明晰,如GCC,make和makefile。
    GCC:GCC是GNU Compiler Collection(就是GNU编译器套件),也可以简单认为是编译器,它可以编译很多种编程语言(括C、C++、Objective-C、Fortran、Java等等)make:make工具可以看成是一个智能的批处置工具,它自身并没有编译和链接的功能,而是用类似于批处置的方式通过调用makefile文件中用户指定的命令来停止编译和链接的。makefile,makefile就是GCC命令的集合,make工具就根据makefile中的命令停止编译和链接的cmake,当项目非常大时,手写makefile会非常烦碎,而且不同平台makefile也会不同,所以cmake就是可以根据CMakeLists.txt自动生成makefile。

入门理论

我们已经对于cmake有了一个总体上的认识,接下来就通过官方提供的几个例子介绍下如何使用cmake。

构建单个源文件

项目只要一个源文件,构造如下,我们一般会新建一个目录存储cmake运行的产物,这里我新建了一个build目录。
  1. ├── CMakeLists.txt
  2. ├── build
  3. └── main.cc
复制代码
main.cc的内容如下
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. /**
  4. * power - Calculate the power of number.
  5. * @param base: Base value.
  6. * @param exponent: Exponent value.
  7. *
  8. * @return base raised to the power exponent.
  9. */
  10. double power(double base, int exponent)
  11. {
  12.     int result = base;
  13.     int i;
  14.     if (exponent == 0) {
  15.         return 1;
  16.     }
  17.     for(i = 1; i < exponent; ++i){
  18.         result = result * base;
  19.     }
  20.     return result;
  21. }
  22. int main(int argc, char *argv[])
  23. {
  24.     if (argc < 3){
  25.         printf("Usage: %s base exponent \n", argv[0]);
  26.         return 1;
  27.     }
  28.     double base = atof(argv[1]);
  29.     int exponent = atoi(argv[2]);
  30.     double result = power(base, exponent);
  31.     printf("%g ^ %d is %g\n", base, exponent, result);
  32.     return 0;
  33. }
复制代码
CMakeLists.txt的内容如下:
  1. # Cmake的最低版本号的要求
  2. cmake_minimum_required (VERSION 2.8)
  3. # 项目信息
  4. project (Demo1)
  5. # 指定生成目的
  6. add_executable(Demo main.cc)
复制代码
在build目录下执行cmake .. 然后执行make命令就可以得到Demo1的可执行文件。

同一个目录,多个源文件

假设我们将Demo1中main.cc的power函数抽取出来放到MathFunctions.cc中,项目构造如下:
  1. ├── CMakeLists.txt
  2. ├── MathFunctions.cc
  3. ├── MathFunctions.h
  4. ├── build
  5. └── main.cc
复制代码
那么该如何编译呢,我们可以通过在add_executable命令中增加将MathFunctions.cc,效果如下add_executable(Demo main.cc MathFunctions.cc),但是假设有很多文件的情况下,一个文件一个文件的添加很费事,cmake提供了aux_source_directory命令,该命令会查找指定目录下所有的源文件,然后将结果存到指定的变量名。CMakeLists.txt文件内容如下
  1. # CMake 最低版本号要求
  2. cmake_minimum_required (VERSION 2.8)
  3. # 项目信息
  4. project (Demo2)
  5. # 查找目录下的所有源文件
  6. # 并将名称保管到 DIR_SRCS 变量
  7. aux_source_directory(. DIR_SRCS)
  8. # 指定生成目的
  9. add_executable(Demo ${DIR_SRCS})
复制代码
多个目录多个源文件

如今我们将MathFounction.h和MathFounction.cpp挪动到math目录下,项目构造如下:
  1. ├── CMakeLists.txt
  2. ├── build
  3. ├── main.cc
  4. └── math
  5.     ├── CMakeLists.txt
  6.     ├── MathFunctions.cc
  7.     └── MathFunctions.h
复制代码
面对这种情况我们需要在Demo3目录下和math目录下各自编写一个CmakeLists.txt文件,我们可以将math目录里面的文件编译成静态库再由main函数调用。 Demo3目录下的CMakeLists.txt内容如下
  1. # CMake 最低版本号要求
  2. cmake_minimum_required (VERSION 2.8)
  3. # 项目信息
  4. project (Demo3)
  5. # 查找目录下的所有源文件
  6. # 并将名称保管到 DIR_SRCS 变量
  7. aux_source_directory(. DIR_SRCS)
  8. # 添加 math 子目录
  9. add_subdirectory(math)
  10. # 指定生成目的
  11. add_executable(Demo ${DIR_SRCS})
  12. # 添加链接库
  13. target_link_libraries(Demo MathFunctions)
复制代码
add_subdictory(math)指明本项目包含一个子目录math,这样,math目录下的CMakeLists.txt文件和源代码也会被使用,最后一行target_link_libraries指明可执行文件需要链接一个名为MathFunctions的链接库。math目录下CMakeLists.txt内容如下
  1. # 查找当前目录下的所有源文件
  2. # 并将名称保管到 DIR_LIB_SRCS 变量
  3. aux_source_directory(. DIR_LIB_SRCS)
  4. # 指定生成 MathFunctions 链接库
  5. add_library (MathFunctions ${DIR_LIB_SRCS})
复制代码
该文件中使用命令add_library将src目录中源文件编译为静态链接库

自定义编译选项

CMake允许为项目增加编译选项,从而可以根据用户的环境和要求选择最适宜的编译方案,例如可以将MathFunctions库设置为一个可选的库,假设该选项为ON,则使用该库定义的函数来停止运算,否则就调用规范库的数学函数库。 为了实现这样的目的我们需要在顶层的CMakeLists.txt中添加该选项,其内容如下
  1. cmake_minimum_required (VERSION 2.8)
  2. # 项目信息
  3. project (Demo4)
  4. set(CMAKE_INCLUDE_CURRENT_DIR ON)
  5. # 是否使用自己的 MathFunctions 库
  6. option (USE_MYMATH
  7.            "Use provided math implementation" ON)
  8. # 参与一个配置头文件,用于处置 CMake 对源码的设置
  9. configure_file (
  10.   "${PROJECT_SOURCE_DIR}/config.h.in"
  11.   "${PROJECT_BINARY_DIR}/config.h"
  12.   )
  13. # 是否参与 MathFunctions 库
  14. if (USE_MYMATH)
  15.   include_directories ("${PROJECT_SOURCE_DIR}/math")
  16.   add_subdirectory (math)
  17.   set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
  18. endif (USE_MYMATH)
  19. # 查找当前目录下的所有源文件
  20. # 并将名称保管到 DIR_SRCS 变量
  21. aux_source_directory(. DIR_SRCS)
  22. # 指定生成目的
  23. add_executable (Demo ${DIR_SRCS})
  24. target_link_libraries (Demo  ${EXTRA_LIBS})
复制代码
其中configure_file命令用于参与一个配置文件config.h,这个文件由CMake从config.h.in生成,通过这样的机制可以通过预定义一些参数和变量来控制代码的生成,config.h.in内容如下:
  1. #cmakedefine USE_MYMATH
复制代码
其中的option命令添加了一个USE_MYMATH选项,并且默认值为ON。之后根据USE_MYMATH变量的值决定是否使用我门自己编写的MathFounctions库
然后需要更改main.cc文件让其根据USE_MYMATH的值确定是否调用规范库,内容如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <config.h>
  4. #ifdef USE_MYMATH
  5.   #include <MathFunctions.h>
  6. #else
  7.   #include <math.h>
  8. #endif
  9. int main(int argc, char *argv[])
  10. {
  11.     if (argc < 3){
  12.         printf("Usage: %s base exponent \n", argv[0]);
  13.         return 1;
  14.     }
  15.     double base = atof(argv[1]);
  16.     int exponent = atoi(argv[2]);
  17. #ifdef USE_MYMATH
  18.     printf("Now we use our own Math library. \n");
  19.     double result = power(base, exponent);
  20. #else
  21.     printf("Now we use the standard library. \n");
  22.     double result = pow(base, exponent);
  23. #endif
  24.     printf("%g ^ %d is %g\n", base, exponent, result);
  25.     return 0;
  26. }
复制代码
值得注意的是这里引入了一个config.h,这个文件预定义了 USE_MYMATH 的值。但我们并不直接编写这个文件,而是由CMake根据config.h.in自动生成。

最后

这篇文章主要介绍了cmake的简单使用,更多关于cmake构建系统的资料请关注网站其它相关文章!

回复

举报 使用道具

相关帖子
全部回复
暂无回帖,快来参与回复吧
本版积分规则 高级模式
B Color Image Link Quote Code Smilies

二了吧唧
注册会员
主题 21
回复 24
粉丝 0
|网站地图
快速回复 返回顶部 返回列表