CMake学习记录

CMake是一个开源跨平台的自动化构建工具

第一章、CMake语法

1.1、打印——message

message("hello")
message([[hello]])

1.2、变量操作set、list

  • CMake的变量分为CMake提供与自定义两种
  • CMake变量的命名区分大小写
  • CMake中的变量在存储时都是字符串
  • CMake获取变量:${变量名}
  • 变量的基本操作是set()与unset(),但也可以利用list或者string操作变量

1.2.1、Set方法:

  • set(<variable><variable>[PARENT_SCOPE])
  • set可以给一个变量设多个值
  • 变量内部存储时使用“;”分割,但显示是只进行连接处理
#设置单个值
set(Var1 zzz)
message(${Var1})

set([[my Var1]] zzz)
message(${my\ Var1})

#设置多个值
set(Var1 v1 v2)
message(${Var1})

set(Var1 v1;v2)
message(${Var1})

#环境变量PATH
message($ENV{PATH})
#创建新的环境变量
set(ENV{CXX} "g++")
message($ENV{CXX})

#unset
unset(ENV{CXX})
message($ENV{CXX})

1.2.2、List方法:

  • list(APPEND <list> [<element>....]) 列表添加元素
  • list(REMOVE_ITEM <list> <value> [value.....]) 列表删除元素
  • list(LENGTH <list> <output variable>) 获取列表元素个数
  • list(FIND <list> <value> <out-var>) 在列表中查找元素返回索引
  • list(INSERT <list> <index> [<element>...]) 在index位置插入
  • list(REVERES <list>) 反转list
  • list(SORT <list> [....]) 排序list
#创建var
list(APPEND port p1 p2 p3)
#添加
list(INSERT port 3 p4)
message(${port})

#获取长度
list(port LISTVALUE len)
message(${len})

#查找索引
list(FIND port p2 index)
message(${index})

#删除
list(REMOVE_ITEM port p1)
message(${port})

#反转
list(REVERSE port)
message(${port})

#排序
list(SORT port)
message(${port})

1.3、流程控制

1.3.1、if条件流程控制

set(VARBOOL TRUE)

#打印TRUE
if(VARBOOL)
   message(TRUE)
else()
   message(FALSE)
endif()

#打印FALSE
if(NOT VARBOOL)
   message(TRUE)
else()
   message(FALSE)
endif()

#打印TRUE
if(NOT VARBOOL OR VARBOOL )
   message(TRUE)
else()
   message(FALSE)
endif()

#打印FALSE
if(NOT VARBOOL AND VARBOOL )
   message(TRUE)
else()
   message(FALSE)
endif()

#打印 1 LESS 2
if(1 LESS 2 )
   message("1 LESS 2")
endif()


#不打印
if("ok" LESS 2 )
   message("ok LESS 2")
endif()

#打印EQUAL 
if("2" EQUAL 2 )
   message("EQUAL ")
endif()

1.3.2、loop循环流程控制

foreach(VAR RANGE 3)
   message(${VAR})
endforeach()


#先打印VAR再打印4,最后再打印f
set(MY_LIST 1 2 3)

foreach(VAR IN LISTS MYLIST ITEM 4 f)
    message($VAR)
endforeach


#两个列表
set(L1 one two three four)
set(L2 1 2 3 4 5)

foreach(num IN ZIP_LISTS L1 L2)
     message("word= ${num_0},num=${num1}")
endforeach()

1.4、Function函数

  • function(<name>[<argument>...])<commands>endfunction()
function(MYFunc FirstArg)
    #CMAKE_CURRENT_FUNCTION函数名称
    message("MYFunc Name:${CMAKE_CURRENT_FUNCTION}")
    message("FirstArg ${FirstArg}")
    set(FirstArg "New Value")
    message("FirstArg again: ${FirstArg}")
    #第0个参数ARGV0
    message("ARGV0 ${ARGV0}")
    message("ARGV1 ${ARGV1}")
    message("ARGV2 ${ARGV2}")
endfunction()

set(FirstArg "first value")
MyFunc(${FirstArg} "value")
message("FirstArg ${FirstArg}")

#输出结果
MYFunc Name: MYFunc
FirstArg first value
FirstArg again: New Value
ARGV0 first value
ARGV1 value
ARGV2

1.5、Scope作用域

CMake有两种作用域

  • Function scope 函数作用域
  • Directory scope:当从add_subdirectory()命令执行嵌套目录中的CMakeLists.txt列表文件时,注意父CMakeLists.txt其中的变量可以被子CMakeLists.txt使用

1.5.1、Function scope

function(OutFunc)
   message("-> Out: ${Var}")
   set(Var 2)
   InFunc()
   message("<- Out: ${Var}")
endfunction()

function(InFunc)
    message("-> In:${Var}")
    set(Var 3)
    message("<- In:${Var}")
endfunction()

set(Var 1)
message("-> Global: ${Var}")
OutFunc()
message("<- Global: ${Var}")

#输出结果
-> Global:1
-> Out:1
-> In:2
<- In:3
<- Out:2
<- Global:1

1.6、宏

注意:尽量不要写宏,只要会读就行

 

macro(Test myVar)
    set(myVal "new value")
    message("argument: ${myVar}")
endmacro()

set(myVar "First value")
message("myVar: ${myVar}")
Test("value")
message("myVar: ${myVar}")

#输出结果
myVar: First value
argument: value
myVar: new value

第二章、CMake构建项目的四种方式

2.1、直接写入源码路径的方式

  • add_executable中直接写入相对路径
  • 在源码中引入头文件时需要写相对路径
cmake_minimum_required(VERSION 3.14)
#指定项目名称
project(ProjectName VERSION 0.1 LANGUAGES CXX)

add_executable(ProjectName
              main.cpp
              pro.cpp
)

2.2、调用子目录中的CMake脚本的方法

  • include方法可以引入子目录中的cmake后缀的配置文件
  • 将配置加入add_executable中
cmake_minimum_required(VERSION 3.14)
#指定项目名称
project(ProjectName VERSION 0.1 LANGUAGES CXX)

#如果调用其他cmake中的使用include(xxxxx.camke)添加进去
set(pro_sources pro.cpp)
add_executable(ProjectName main.cpp ${pro_sources})

2.3、CMakeLists嵌套

  • target_include_directories头文件目录的声明
  • target_link_libraries连接库文件
  • add_subdirectory添加子目录
  • add_library生成库文件 
#子
add_library(ProLib pro.cpp)
#父
cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

add_subdirectory("子文件夹名")

add_executable(ProjectName main.cpp)

target_link_libraries(ProjectName PUBLIC ProLib)

#PROJECT_BINARY_DIR表示二进制文件目录,PROJECT_SOURCE_DIR为源码目录
target_include_directories(ProjectName PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/子文件夹名")

2.4、Object Libraries

注意:最低版本为3.12才能使用

  • add_library OBJECT

Object Libraries是一个特殊的库类型,它将目标文件编译成一个库,但不会生成最终的连接文件。这意味着你可以在后续的add_library()或add_executable()命令中,将Object Libraries作为源文件进行链接,从而生成最终的可执行文件或库文件

  • 将target_include _directories移入到子CMakeLists中
#子
#方式一
add_library(ProLib  OBJECT pro.cpp)
target_include_directories(ProLib PUBLIC .)

#方式二
add_library(cat  OBJECT cat.cpp)
target_include_directories(cat PUBLIC .)

add_library(dog  OBJECT dog.cpp)
target_include_directories(dog PUBLIC .)
#父
#方式一
cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

add_subdirectory("子文件夹名")

add_executable(ProjectName main.cpp)

target_link_libraries(ProjectName PUBLIC ProLib)


#方式二
cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

add_subdirectory("子文件夹名")

add_executable(ProjectName main.cpp)

target_link_libraries(ProjectName PUBLIC cat dog)

第三章、CMake与库

3.1、CMake如何生成静态库/动态库

动态库:lib<name>.so/dll

静态库:lib<name>.a/lib

命令:

  • file()用于搜索源文件
  • add_library(xxxx   STATIC ${SRC})生成静态库
  • add_library(xxxx   SHARED ${SRC})生成动态库
  • ${LIBRARY_OUTPUT_PATH}导出目录
cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

#将所有cpp文件加入到SRC变量中
file(GLOB SRC ${PROJECT_SOURCE_DIR}/src/*.cpp)

#引入头文件
include_directories(${PROJECT_SOURCE_DIR}/include)

#静态
#输出文件位置
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/a)

add_library(aniaml STATIC ${SRC})

#动态
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/so)

add_library(aniaml SHARED ${SRC})

3.2、CMake调用动态库与静态库

静态库调用流程

  1. 引入头文件
  2. 连接静态库
  3. 生成可执行二进制文件
cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

#引入头文件
include_directories(${PROJECT_SOURCE_DIR}/include)

#指定路径
link_directories(${PROJECT_SOURCE_DIR}/a)

#链接库
link_libraries(animal)

#生成二进制可执行文件
add_executable(app main.cpp)

动态库调用流程

  1. 引入头文件
  2. 声明库目录
  3. 生成可执行二进制文件
  4. 连接动态库
cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

#引入头文件
include_directories(${PROJECT_SOURCE_DIR}/include)

#指定路径
link_directories(${PROJECT_SOURCE_DIR}/so)

#生成二进制可执行文件
add_executable(app main.cpp)

#链接库
target_link_libraries(app PUBLIC animal)

第四章、CMake与源文件的交互

config.h.in 文件
相当于模板
在这个文件中可以获取CMake文件中的变量
#define CMAKE_CXX_STANDARD ${CMAKE_CXX_STANDARD}
cmake文件

cmake_minimum_required(VERSION 3.14)

project(ProjectName VERSION 0.1 LANGUAGES CXX)

#设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

configure_file(config.h.in config.h)

add_subdirectory(animal)

add_executable(ProjectName main.cpp)

target_link_libraries(ProjectName PUBLIC AnimalLib)

target_include_directories(ProjectName PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/animal")
main.cpp

#include "config.h"
int main()
{
   std::cout<<CMAKE_CXX_STANDARD<<std:endl;
   return 0;
}

第五章、CMake的条件编译

步骤:

  1. 用option定义变量
  2. 在子CMakeLists.txt中根据变量ON还是OFF来修改SRC(源文件)以及target_compile_defintions
  3. 修改源文件根据变量选择代码
  4. 执行命令时-D<变量>=ON/OFF来进行条件编译

注意:

  • PUBLIC :本目标需要用,依赖这个目标的其他目标也需要
  • INTERFACE: 本目标不需要,依赖本目标的其他目标需要
  • PRIVATE:本目标需要,依赖这个目标的其他目标不需要
option(USE_CATTWO "Use cat two" ON)

if(USE_CATTWO)
    set(SRC cat.cpp dog.cpp cattwo.cpp)
else
    set(SRC cat.cpp dog.cpp)
endif()

add_library(AnimalLib ${SRC})
 
if(USE_CATTWO)
    target_compile_definitions(AnimalLib PRIVATE "USE_CATTWO")
endif()
#ifdef USE_CATTWO
    #include  "cattwo.h"
#endif()

std::string Cat::barking()
{
#ifdef USE_CATTWO
    retrun cattwo::two()
    #else
    return "cat mi mi"
    #endif
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值