CMake简易教程,常用语法命令,以及交叉编译

CMake笔记

概述

  • 正常流程:预编译、编译、汇编、链接

  • Visual Studio(集成开发环境IDE:编辑器、编译器VC++、nmake、调试器),比较傻瓜的进行完整的编译流程,不需要开发者干预。禁用VisualStudio后,windows平台下无法使用此流程工具,部分代码也因为引用了VC++的特性,所以也许要进行一定的改造重构

  • cmake优点:跨平台、支持多种编译器:vc++、mingw、crgwin、lcc等,利于开发者掌握代码模块间的关联性;缺点:官方文档比较杂,没有优秀的官方范例,很多配置项有多种配置方式,一些配置项互相影响导致结果与官方文档说明的功能有差异



CMakeLists.txt文件

  • CMakeLists.txt文件是CMake进行编译链接的配置文件,保存了项目信息、代码模块关联性、链接库生成配置、可执行文件生成配置、头文件引用配置等,一般由开发者根据项目内容手动编写,保存在项目的根目录下

  • CMakeLists.txt主要结构:

    1. [项目信息] 可省略
    2. [变量定义] 复杂项目可能需要进行,非必须
    3. [自定义配置选项] 自定义配置处理,非必须
    4. [子项目配置] 多模块开发涉及,非必须
    5. [头文件、库文件引用配置] 应用第三方库或多模块开发涉及,非必须
    6. [编译] 一般add_executable或者add_library即可
    7. [连接] 链接库(动态库、静态库)连接至上一步生成的产物上


涉及语法总览

语法 解释 其他注意事项
project 工程名 非必须
cmake_minimum_required cmake最低版本需求 非必须
${} 引用变量、宏定义等
add_executable 编译可执行文件
add_library 编译库文件
include_directories 设置头文件目录 一般引用第三方库时使用
link_directories 设置库文件目录 一般引用第三方库时使用
message 输出文本信息 多用以调试输出
add_compile_options 设置编译选项 gcc、g++选项
set 设置选项
aux_source_directory 批量引用源文件
options 自定义选项
if(),elseif(),else(),endif() 条件分支


SET常用选项

选项 解释 参数
CMAKE_BUILD_TYPE 编译模式 “Release”,“Debug”
EXECUTABLE_OUTPUT_PATH 设置可执行文件输出目录
CMAKE_ARCHIVE_OUTPUT_DIRECTORY 设置动态库模块导入文件dll.a(lib)输出目录 mingw编译器绝大多数情况不需要,VC编译器必须
CMAKE_RUNTIME_OUTPUT_DIRECTORY 设置链接库输出目录
CMAKE_LIBRARY_OUTPUT_DIRECTORY 设置链接库输出目录 未成功,原因未知

PS:链接库输出选项

  1. CMAKE_ARCHIVE_OUTPUT_DIRECTORY,CMAKE_RUNTIME_OUTPUT_DIRECTORY,CMAKE_LIBRARY_OUTPUT_DIRECTORY在Linux和Windows下的产生的效果不同,可能与CMake版本或者系统差异有关,需要酌情调用,或者全部调用


命令行常用选项

选项 说明 其他注意事项
-version 显示cmake版本信息
-help 显示cmake命令行帮助信息
-G 选择编译器 MinGW编译器一般是"MinGW Makefiles"
-D[选项] 命令行临时修改选项,[选项]参见SET常用选项 如果命令行和CMakeLists.txt里有同样的选项,那么命令行选项设置会失效




详细解析

[项目信息]

project([NAME])项目名称

插入字符串即可

cmake_minimum_required(VERSION 3.0)cmake需求版本

最低版本号,根据所使用的cmake版本可支持的特性来决定,本篇所涉及的特性使用3.0以上即可


[变量定义]

set([NAME] [VALUE])设定变量

一般复杂项目时,部分字符串、文件名会反复调用,定义变量保存,方便编写,使用${NAME}可得到变量值


message(${NAME})输出内容

在cmake准备阶段,message会输出指定变量或者宏的值,方便开发者确认详细配置内容

[自定义配置选项]

option([NAME] [DESCRIPTION] [DEFAULT_VALUE])设置自定义选项

自定义执行选项,可在cmake执行阶段,通过命令行改变选项,一般配合if()else()进行编译分支

NAME-选项名称
DESCRIPTION-描述字符串
DEFAULT_VALUE-默认值ON/OFF或者字符串

if([表达式])…elseif([表达式])…else()…endif() 条件分支

关系运算符 解释
AND
NOT
OR
EXIST 目录、文件是否存在
EQUAL 变量等于
LESS 变量小于
GREATER 变量大于
STREQUAL 字符串等于
STRELESS 字符串小于
STREGREATER 字符串大于

[子项目配置]

add_subdirectory([DIR])添加子项目

运用在多模块项目中,主模块CMakeLists.txt中应用其他模块,DIR目录为绝对路径,该目录下必须要有对应的源文件和CMakeLists.txt

[头文件、库文件引用配置]

include_directories([DIR])添加头文件目录

一般用在引用第三方模块

link_directories([DIR])添加链接库目录

一般用在引用第三方模块

[编译]

add_executable([OUT] [SOURCE FILE LIST])编译可执行文件

  • OUT-可执行文件名
  • SOURCE FILE LIST-编译OUT需要的源文件列表

add_library([OUT] [TYPE] [SOURCE FILE LIST])编译链接库

  • OUT-编译输出的链接库名称,PS:cmake采用Linux命名规则,链接库会自动添加"lib"前缀
  • TYPE-链接库类型:STATIC-静态库,SHARED-动态库;如果不指定,则默认静态库
  • SOURCE FILE LIST-编译OUT需要的源文件列表

aux_source_directory([DIR] [NAME])查找目录中所有源文件

在调用add_executable或add_library时,需要列出全部的源文件。大项目中,源文件如果很多,一个一个添加很复杂,可以使用aux_source_directory自动扫描[DIR]下的全部源文件,赋值给[NAME]变量,再通过NAME引用

aux_source_directory(${CMAKE_SOURCE_DIR}/src CPPS)//扫描CMakeLists.txt所在目录下src目录下的全部源文件,定义为CPPS
add_executable(out CPPS)  //使用CPPS来编译可执行文件out

[连接]

target_link_libraries([OUT] [LIBS])链接库文件

将LIBS的全部库文件链接到[OUT]可执行文件、库文件中

  1. target_link_libraries必须写在add_executable和add_library之后
  2. cmake采用的是Linux命名规则,所以指定LIBS时,如果只写库名,会在库名前加lib,默认优先查找静态库,再查找动态库
  3. LIBS可以指定完整的库文件名
  4. 不建议在一条target_link_libraries中混合使用2,3中的静态、动态、自动查找方式,否则可能会导致未知错误






CMake与交叉编译

由于每个交叉编译链的差异,以及个人部署的环境不同,所以CMake的交叉编译环境,需要根据系统差异进行反复测试才能调试通过
以下为官方文档,且较为通用的配置

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(ARMROOT "/home/ubuntu/arm-linux-gnueabi/")

//设置编译链的主目录(非必须,如果编译出错时,可以尝试加上)
set(CMAKE_SYSROOT ${ARMROOT})

//设置C编译器绝对路径
set(CMAKE_C_COMPILER ${ARMROOT}/bin/arm-linux-gnueabi-gcc)
//设置C++编译器绝对路径
set(CMAKE_CXX_COMPILER ${ARMROOT}/bin/arm-linux-gnueabi-g++)


set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
....
....
....

你可能感兴趣的:(C++,cmake,c++,cmake)