程序员的故乡

 

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)

常用的命令

以下面这个复杂一些的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)
  • 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)

常用变量

${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)

构建开关

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()

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)

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@

导入options

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

#cmakedefine01 USE_SSL

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()

比如这个就扩展了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} $<TARGET_OBJECTS:clickhouse_malloc> $<TARGET_OBJECTS:memcpy>)
    else ()
        add_executable (${ARGV} $<TARGET_OBJECTS:clickhouse_malloc>)
    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()

build目录

build/
    CMakeCache.txt
    CMakeFiles/
    cmake_install.cmake
    Makefile
    Tutorial.exe
    TutorialConfig.h
    MathFunctions/

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

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

MathFunction是库的目录。

更进一步

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

posted on 2023-09-10 21:28  程鑫  阅读(58)  评论(0编辑  收藏  举报

导航