cmake 编译工具小记

cmake

cmake 初探

什么是CMAKE

  • CMake是一种跨平台编译工具。
  • 首先编写CMakeLists.txt文件,然后通过cmake命令将CMakeLists.txt文件转化为对应平台可执行的make文件,最后用make命令编译源码生成可执行程序或库文件,从而避免不同平台Makefile格式的问题。

C/C++的编译过程

  • 编译过程实际上就是将一种语言(通常为高级语言)翻译为成另一种语言(通常为低级语言)。 C/C++程序编译的主要流程:源代码 → 预处理器 → 编译器 → 汇编器 → 链接器 → 可执行程序

  • 预处理: C/C++中,在编译器对源文件进行编译之前,先要对其进行预处理。

    • 预处理器提供了一组预编译处理指令和预处理操作符,形式上以#开头,实际上并不属于C/C++中的语句,不能被编译程序翻译,需要在真正编译之前做一个预处理,最后输出一个“.i”文件。
  • 编译: 编译就是把C/C++代码转换成汇编代码。

    • 编译程序需要通过词法分析和语法分析,在确认所有的指令都符合语法规则没有语法错误之后,把代码转换成汇编语言,生成汇编代码。
  • 汇编: 汇编就是将上一步输出的汇编代码翻译成目标机器指令的过程,生成的目标文件是与源程序等效的机器语言。

  • 链接: 链接就是将汇编生成的目标文件、系统库的目标文件、库文件链接起来,生成可以在某一特定平台运行的可执行程序。

CMake 常用变量

  • CMAKE_BINARY_DIRPROJECT_BINARY_DIR<projectname>_BINARY_DIR
    • 这三个变量指代的内容是一致的, 如果是 in source 编译,指得就是工程顶层目录,
    • 如果是 out-of-source 编译,指的是工程编译发生的目录。
    • PROJECT_BINARY_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。
  • CMAKE_SOURCE_DIRPROJECT_SOURCE_DIR <projectname>_SOURCE_DIR
    • 这三个变量指代的内容是一致的,不论采用何种编译方式, 都是工程顶层目录。
    • 在 in source 编译时,他跟 CMAKE_BINARY_DIR 等变量一致。
  • CMAKE_CURRENT_SOURCE_DIR
    • 指的是当前处理的 CMakeLists.txt 所在的路径,比如上面我们提到的 src 子目录。
  • CMAKE_CURRRENT_BINARY_DIR
    • 如果是 in-source 编译,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 out-of-source 编译,他指的是 target 编译目录。
    • 使用我们上面提到的 ADD_SUBDIRECTORY(src bin)可以更改这个变量的值。
    • 使用 SET(EXECUTABLE_OUTPUT_PATH <新路径>)并不会对这个变量造成影响,它仅仅修改了最终目标文件存放的路径。
  • CMAKE_MODULE_PATH
    • 这个变量用来定义自己的 cmake 模块所在的路径。
    • Eg:SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),这时候你就可以通过 INCLUDE 指令来调用自己的模块了。
  • EXECUTABLE_OUTPUT_PATHLIBRARY_OUTPUT_PATH
    • 分别用来重新定义最终结果的存放目录,前面我们已经提到了这两个变量。

如何编写cmake

  • cmake_minimum_required(VERSION 3.16):用于指定cmake最低版本需求;
    project(projectName) :用于指定项目名称;
    include_directories() :用于引入头文件搜索路径;
    aux_source_directory(src dir_srcs):用于包含源文件目录;
    set(TEST_MATH) :用于设置环境变量,编译用到的源文件全部都要放到这里;
    add_executable(${PROJECT_NAME} ${TEST_MATH}):用于添加要编译的可执行文件;
    target_link_libraries(${PROJECT_NAME} m):用于添加可执行文件所需要的库;
    
  • 新建变量,存放源文件:

    • set (SRC_LIST ./main.c ./func.c ./func1.c)
  • 不同目录下多个源文件

    • 添加指定头文件的搜索路
      • include_directories (func1 func2)
    • 搜索指定路径下的所有源文件,并保存在变量中
      • aux_source_directory (func1 SRC_LIST1)
  • 向当前工程添加存放源文件的子目录

    • add_subdirectory (src)
  • 将生成的可执行文件存放到工程根目录下的bin目录下

    • set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
  • 对库的链接

    • 将指定目录下的指定库文件存到变量FUNC_LIB
      • find_library(FUNC_LIB func HINTS ${PROJECT_SOURCE_DIR}/func/lib)
      • find_library:在指定目录下查找指定库,并把库的绝对路径存放到变量里,参数一是变量名,参数二是库名,参数三是HINTS,参数四是路径。
      • 使用find_library的好处是在执行cmake ..时就会去查找库是否存在,这样可以提前发现错误,不用等到链接时。

添加编译选项:

  • 有时编译程序时想添加一些编译选项,如-Wall,-std=c++11等,就可以使用add_compile_options来进行操作。
    • add_compile_options(-std=c++11 -Wall)
      • 添加C++ 11标准支持,并让编译器对代码提出尽可能多的警告

添加控制选项

option命令: 参数1为option的名字,参数2为字符串,描述option的功能,参数3为option的值,ON或OFF,也可以不写默认为OFF。

第一:CMakeList 中条件编译

  • option(MYDEBUG "enable debug compilation" OFF)

    • if (MYDEBUG)
          add_executable(main2 main2.c)
      else()
          message(STATUS "Currently is not in debug mode")    
      endif()
      
  • cmake .. -DMYDEBUG=ON命令 控制

第二:代码中条件编译

  • CMakeList 中添加

    • option(WWW1 "print one message" OFF)
      # 这儿`OFF、False`  `ON、True` 都可以
      if (WWW1)
      	add_compile_options(-DWWW1)
      endif()
      
    • cmake中加这个,目的就是代码中可以使用该变量

  • *.h*.cpp中 案例:

    • #ifdef WWW1
          printf("---  define  WWW1\n");
      #else
      	printf("---- not define  WWW1\n");
      #endif
      

Cmake 进阶

//TODO

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值