CMake基本概念

        CMake可通过与平台无关的CMakeList.txt来定制整个编译流程,然后根据目标用户的平台进一步生成适配该平台的Makefile来编译构建工程的。

        用CMake编译时,首先执行cmake path,将会按CMakeLists.txt所指定的规则生成Makefile,其中path为CMakeLists.txt所在的路径。然后使用make命令按照生成Makefile进行编译。

1. CMakeLists.txt

1.1 基本格式

cmake_minimum_required(VERSION 3.10)

#set the project name
project(Tutorial)

#add the executable
add_executable(Tutorial tutorial.cxx)

1.2 环境变量

cmake-variables

BINARY

  • CMAKE_BINARY_DIR :binary files的主路径

  • CMAKE_CURRENT_BINARY_DIR: 当前编译的路径

  • PROJECT_BINARY_DIR: 当前工程编译的路径

SOURCE

  • CMAKE_SOURCE_DIR:  源码主路径
  • CMAKE_CURRENT_SOURCE_DIR: 当前子工程的源码路径
  • PROJECT_SOURCE_DIR:  当前编译工程的源码路径

NAME

  •  PROJECT_NAME: 当前project name
  • CMAKE_PROJECT_NAME: 第一个被创建的project name

 1.3 命令

  • include(file/module)

        Load and run CMake code from a file or module

        如果是module,cmake将会在CMAKE_MODULE_PATH或Cmake module的路径下找module.cmake

  • set(source, a.cpp b.cpp c.cpp)

        设置source变量为a, b,c.cpp, 之后${source}指代a, b, c.cpp

  • target_include_directories(target  PRIVATE/PUBLIC/INTERFACE  include)

        编译该target时会将include路径下的头文件编译进去

        PRIVATE:  该include只被加载到该target中;

        PUBLIC:     若target为library,该include不仅会编译进该library,其他任何链接该library的 target都会加载该include;

        INTERFACE:  该include可以被添加到任何链接该library的target的include directories, 但该target本身并不会被编译

  • target_link_libraries(target PRIVATE libaray)

        编译该target时会将libaray链接进去

  • add_library(libaray STATIC/SHARED/ALIAS source)

        依赖source生成library

        参数可选static, shared, 分别生成静态库libxxx.a或动态库libxxxx.so

        alias: 类似于target别名,用来指代target;

        add_library(project_name INTERFACE) : 当创建的library只依赖头文件时,用INTERFACE来创建无任何输出的target。

  • install (TARGETS/DIRECTORY/FILES  source DESTINATION dest)

        install一般在放在CMakeLists.txt的最后一个模块,编译完成后,执行make install, 可以将source copy到dest中, 其中source可以是targets, directory,或者files。

         另外,如果是library a, 因为是未编译完成的target,所以,要用TARGETS模式,且用"a LIBRARY"来指代编译生成的libaray a。

        若dest非绝对路径,将默认放在base install location下的dest下。the base install location是由CMAKE_INSTALL_PREFIX来控制,一般可通过"cmake .. -DCMAKE_INSTALL_PREFIX = ${CMAKE_BINARY_DIR}"来设置,或者运行"make install DESTDIR=/tmp/stage", 将会创建安装路径${DESTDIR}/${CMAKE_INSTALL_PREFIX}做为base install location.

  • 编译类型

        一般有以下的编译类型:

        Release:   编译时添加"-O3 -DNDEBUG" flags

        Debug: "-g"

        MinSizeRel: "-Os -DNDEBUG"

        RelWithDebInfo:  "-O2 -g -DNDEBUG"

        编译类型可以通过"cmake .. -DCMAKE_BUILD_TYPE=Release"来指定。若没有指定具体的类型,可用以下方式来设置默认的编译类型。

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    message("Setting build type to 'RelWithDebInfo' as none was specified.")
    set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
    # Set the possible values of build type for cmake-gui
    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
      "MinSizeRel" "RelWithDebInfo")
endif()
  • 编译flag

        CMAKE_CXX_FLAGS: c++

        CMAKE_C_FLAGS: c

        CMAKE_LINKER_FLAGS: linker flags

        设定方式一:set

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE)

        其中,"CACHE STRING "Set C++ Compiler Flags" FORCE"用于使CMake flags可以在CMakeCache.txt中进行设置。

        设定方式二:target_complie_definitions

target_compile_definitions(cmake_examples_compile_flags
     PRIVATE EX3)

        上述方式将在编译target时,添加-DEX3,即定义了EX3的宏。

        一旦设定了编译flag,所有targets将会按设定的flag进行编译。

  • find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)

        Boost: 要找的library name

        1.46.1:要找的Boost最低版本

        REQUIRED: 表示这个是必需的,如果找不到将会失败;

        COMPONENTS: the list of components to find in the library

        如果找到对应的package,将会创建XX_FOUND变量,可以用这个变量来检测是否找到对应的package, 用XX_INCLUDE_DIRS来指代找到的package的头文件的位置, 如: Boost_INCLUDE_DIRS。用XX_LIBRARY来指代library的位置。

 if(Boost_FOUND)
     message ("boost found")
     include_directories(${Boost_INCLUDE_DIRS})
 else()
     message (FATAL_ERROR "Cannot find Boost")
 endif()
  • 编译器设定

        CMAKE_C_COMPILER: c

        CMAKE_CXX_COMPILER: C++

        CMAKE_LINKER:  用于编译时链接binary        

  • 设置c++ standard

        方式一:

 include(CheckCXXCompilerFlag)
 CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
 CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
                                                                                                                                                                                                          
 # check results and add flag
 if(COMPILER_SUPPORTS_CXX11)#
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 elseif(COMPILER_SUPPORTS_CXX0X)#
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
 else()
     message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
 endif()

        include(CheckCXXCompilerFlag):  告诉cmake把这个函数包含进来以使用;

        cmake支持尝试用传进CHECK_CXX_COMPILER_FLAG中的任何flags进行编译,并把结果放在传进这个函数的变量中,用于判断当前环境是否支持该flags。

        方式二:

set(CMAKE_CXX_STANDARD 11)

        设置CMAKE_CXX_STANDARD后, CMake将会在编译时设置合适的,与设置最接近的flags,并把将其作用于所有targets。

        方式三:

target_compile_features(target PUBLIC cxx_auto_type)

message("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}")

    cmake自动选择合适的编译flags。

    可以用${CMAKE_CXX_COMPILE_FEATURES}来列出所有的features。

  • add_subdirectory(subdir)

        添加subdir,并按subdir下的CMakeLists.txt进行编译;

        当用project()创建project时,CMake将会自动为该project创建一系列的变量,这些变量将可以被其他project或主project使用。

  • configure_file(ver.h.in ${PROJECT_BIANARY_DIR}/ver.h)

        根据ver.h.in构建生成ver.h, 其中ver.h.in可以使用cmake及CMakeLists.txt中定义的变量,如,${PROJECT_BIANARY_DIR};

1.4 控制流程

  • if..elseif..else

if(<condition>)
  message("do stuff")
elseif(<condition>)
  message("do other stuff")
else()
  message("do other other stuff")
endif()
  • Loops

set(list 1 2 bar)
foreach(var ${list} foo)
    message("the val is "${var})
endforeach()

#运行结果: 
the val is 1
the val is 2
the val is bar
the val is foo

1.5 modules, functions and macros

        functions与macros用法是类似的,但不同的是functions有自己的scope,但macros没有,因此定义在macros中的变量将会在全scope中被用到,因此,macros适合较为简短精炼的function。

        function与macros另一点不同的地方是参数传递的方式,macros的参数不是设定为variables,而是间接引用,或者可理解为直接展开,因此,要注意避免;

macro(print_list my_list)
  foreach(var IN LISTS my_list)
    message("${var}")
  endforeach()
endmacro()

set(my_list a b c d)
set(my_list_of_numbers 1 2 3 4)
print_list(my_list_of_numbers)
# prints:
# a
# b
# c
# d

1.6 protobuf

        protocol buffers是一种数据序列化格式,使用.proto来描述数据,可用protobuf编译器将其转化为c++的源码。

PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS AddressBook.proto)

 # Add an executable
 add_executable(protobuf_example
     main.cpp
     ${PROTO_SRCS}
     ${PROTO_HDRS})
 
 target_include_directories(protobuf_example
     PUBLIC
     ${PROTOBUF_INCLUDE_DIRS}
     ${CMAKE_CURRENT_BINARY_DIR}
 )

 # link the exe against the libraries
 target_link_libraries(protobuf_example
     PUBLIC
     ${PROTOBUF_LIBRARIES}
  ) 

        在编译target时,会启动protobuf compiler。

        在生成的FindProtobuf.cmake中存着各种可用的protobuf变量,如:

        PROTOBUF_INCLUDE_DIRS: protobuf 头文件

        PROTOBUF_LIBRARIES:  protobuf library

CMake入门实战​​​​​​effective modern cmake

cmake-example

Cmake tutorial

CMake reference documentation

cmake资料汇总

Cpp presentations

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CMake是一个用于管理项目构建过程的开源工具。它通过配置文件的方式来定义源代码、编译器选项、库依赖和构建规则等信息,并根据这些信息生成针对不同平台和编译器的构建脚本。 CMake的教程可以帮助我们更好地理解和使用这个工具。在教程中,我们可以学习到CMake基本概念、语法和用法,以及如何编写CMakeLists.txt文件来定义项目的构建过程。 教程一般会从简单的示例开始,逐步介绍CMake的各个方面。首先,我们可以学习如何定义基本的项目信息,如项目名称、版本号和语言要求。然后,我们可以了解如何添加源代码文件、头文件目录和编译选项。接着,我们可以学习如何定义库依赖和链接选项,以及如何生成可执行文件或库文件。 教程还可以教我们如何使用CMake的命令来进行条件编译、循环遍历和文件查找等操作。此外,教程还会介绍如何使用CMake的变量、宏和函数来简化构建过程和提高代码的可读性。 通过学习CMake的教程,我们可以更加高效地管理和构建项目,提高代码的可维护性和可移植性。无论是小型项目还是大型项目,CMake都可以帮助我们更好地组织代码、管理依赖和发布软件。 总之,CMake的教程是学习和使用CMake的重要资源,它可以帮助我们掌握CMake基本概念和用法,提高项目的构建效率和质量。希望通过学习CMake的教程,我们能够更加熟练地使用这个工具,为我们的项目开发和维护带来便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值