• cmake简略使用介绍


    cmake简略

    构建系统对于一个大型项目至关重要,本身就可以看成大项目中的一个子项目。cmake是C++生态环境中常用的构建工具。这里简单介绍一下cmake的用法。

    最简单的例子

    cmake_minimum_required(VERSION 3.15)
    
    # set the project name
    project(Tutorial)
    
    # add the executable
    add_executable(Tutorial tutorial.cpp)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    常用的命令

    以下面这个复杂一些的CMakeLists.txt文件内容为例:

    cmake_minimum_required(VERSION 3.15)
    
    # set the project name
    project(Tutorial)
    
    set(SRC_LIST tutorial.cpp)
    
    option(USE_MYMATH "Use tutorial provided math implementation" ON)
    
    # add the executable
    add_executable(${PROJECT_NAME} ${SRC_LIST})
    
    # add the library
    add_library(MathFunctions MathFunctions/mysqrt.cpp)
    
    configure_file(TutorialConfig.h.in TutorialConfig.h)
    
    target_include_directories(${PROJECT_NAME} PUBLIC
                               ${PROJECT_BINARY_DIR}
                               )
    
    target_link_libraries(${PROJECT_NAME} PUBLIC MathFunctions)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • cmake_minimum_required(VERSION 3.15)
      要求cmake最低版本
    • project(Tutorial)
      设置项目名称
    • set(SRC_LIST tutorial.cpp)
      设置变量
    • option(USE_MYMATH “Use tutorial provided math implementation” ON)
      设置构建选项
    • add_executable(${PROJECT_NAME} ${SRC_LIST})
      添加可执行文件作为构建目标
    • add_library(MathFunctions MathFunctions/mysqrt.cpp)
      添加库作为构建目标
    • configure_file(TutorialConfig.h.in TutorialConfig.h)
      根据模板替换模板中的内容生成包含配置信息的头文件
    • target_include_directories
      target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR} )
      为构建目标添加include目录
    • target_link_libraries(${PROJECT_NAME} PUBLIC MathFunctions)
      为构建目标链接静态库。

    设置变量

    list(APPEND EXTRA_LIBS MathFunctions)
    set(SRC_LIST a.cpp b.cpp c.cpp)
    string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
    unset(SRC_LIST)
    
    • 1
    • 2
    • 3
    • 4

    常用变量

    ${PROJECT_NAME}

    ${PROJECT_SOURCE_DIR}

    ${PROJECT_BINARY_DIR}

    ${CMAKE_ROOT}

    ${CMAKE_CURRENT_BINARY_DIR}

    ${CMAKE_CURRENT_SOURCE_DIR}

    控制编译器行为

    set (CMAKE_CXX_STANDARD 23)
    set (CMAKE_CXX_EXTENSIONS OFF)
    set (CMAKE_CXX_STANDARD_REQUIRED ON)
    
    • 1
    • 2
    • 3

    构建开关

    option定义构建开关,以下面为例:

    option(USE_MYMATH "Use tutorial provided math implementation" ON)
    if(USE_MYMATH)
      add_subdirectory(MathFunctions)
      list(APPEND EXTRA_LIBS MathFunctions)
      list(APPEND EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/MathFunctions)
    endif()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    cmake的信息到源代码

    在这个例子中,在CMakeLists.txt文件中定义几个版本和构建时间的变量,然后通过configure_file生成头文件。

    CMakeLists.txt

    set (Tutorial_VERSION_MAJOR 1)
    set (Tutorial_VERSION_MINOR 0)
    set (Tutorial_VERSION_PATCH 12)
    string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
    
    configure_file(TutorialConfig.h.in TutorialConfig.h)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    TutorialConfig.h.in

    // the configured options and settings for Tutorial
    #define Tutorial_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
    #define Tutorial_VERSION_MINOR @PROJECT_VERSION_MINOR@
    #define Tutorial_VERSION_PATCH @PROJECT_VERSION_PATCH@
    
    #define TIMESTAMP @COMPILE_TIME@
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    导入options

    假设USE_SSL是cmake定义的option,option(USE_SSL "Use SSL" ON)。在config.h.in中可以这样定义并获得option的值。

    #cmakedefine01 USE_SSL
    
    • 1

    Macro

    cmake的macro可以是很强大的。

    比如这个就很有用,用于添加源代码文件到变量里。

    macro(add_glob cur_list)
        file(GLOB __tmp CONFIGURE_DEPENDS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${ARGN})
        list(APPEND ${cur_list} ${__tmp})
    endmacro()
    
    macro(add_headers_and_sources prefix common_path)
        add_glob(${prefix}_headers ${CMAKE_CURRENT_SOURCE_DIR} ${common_path}/*.h)
        add_glob(${prefix}_sources ${common_path}/*.cpp ${common_path}/*.c ${common_path}/*.h)
    endmacro()
    
    macro(add_headers_only prefix common_path)
        add_glob(${prefix}_headers ${CMAKE_CURRENT_SOURCE_DIR} ${common_path}/*.h)
    endmacro()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    比如这个就扩展了add_executable的功能,创建了一个更强大的add_executable

    macro (clickhouse_add_executable target)
        # invoke built-in add_executable
        # explicitly acquire and interpose malloc symbols by clickhouse_malloc
        # if GLIBC_COMPATIBILITY is ON and ENABLE_THINLTO is on than provide memcpy symbol explicitly to neutrialize thinlto's libcall generation.
        if (ARCH_AMD64 AND GLIBC_COMPATIBILITY AND ENABLE_THINLTO)
            add_executable (${ARGV} $ $)
        else ()
            add_executable (${ARGV} $)
        endif ()
    
        get_target_property (type ${target} TYPE)
        if (${type} STREQUAL EXECUTABLE)
            # disabled for TSAN and gcc since libtsan.a provides overrides too
            if (TARGET clickhouse_new_delete)
                # operator::new/delete for executables (MemoryTracker stuff)
                target_link_libraries (${target} PRIVATE clickhouse_new_delete)
            endif()
    
            # In case of static jemalloc, because zone_register() is located in zone.c and
            # is never used outside (it is declared as constructor) it is omitted
            # by the linker, and so jemalloc will not be registered as system
            # allocator under osx [1], and clickhouse will SIGSEGV.
            #
            #   [1]: https://github.com/jemalloc/jemalloc/issues/708
            #
            # About symbol name:
            # - _zone_register not zone_register due to Mach-O binary format,
            # - _je_zone_register due to JEMALLOC_PRIVATE_NAMESPACE=je_ under OS X.
            # - but jemalloc-cmake does not run private_namespace.sh
            #   so symbol name should be _zone_register
            if (ENABLE_JEMALLOC AND OS_DARWIN)
                set_property(TARGET ${target} APPEND PROPERTY LINK_OPTIONS -u_zone_register)
            endif()
        endif()
    endmacro()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    build目录

    build/
        CMakeCache.txt
        CMakeFiles/
        cmake_install.cmake
        Makefile
        Tutorial.exe
        TutorialConfig.h
        MathFunctions/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Makefile 是 cmake 根据顶级 CMakeLists.txt 生成的构建文件,通过该文件可以对整个项目进行编译。

    Tutorial.exe 就是生成的可执行文件,通过该文件运行程序。

    MathFunction是库的目录。

    更进一步

    cmake其实是一个语言,可以简单地使用其基本功能,也可以复杂地把它当成一门编程语言。
    cmake详细介绍 说得更加详细。

  • 相关阅读:
    免申请直接用上 IDEA 新 UI,只需要这三步配置
    NewStarCTF2023week3-Rabin‘s RSA
    vue中常见的3块标签的介绍
    3D可视化项目,选择unity3D还是three.js,是时候挑明了。
    如何用 vscode 捞出还未国际化的中文词条
    redis的基础底层篇 zset的详解
    Objective-C依然占C位,Swift和SwiftUI在iOS 15中的使用情况
    Linux top 命令详解
    tomcat 端口 8005 被 windows 系统服务占用导致启动闪退的问题
    10BGP community属性
  • 原文地址:https://blog.csdn.net/Ahxing1985/article/details/132795900