Cmake项目构建教程

cmake


CMake 是一个跨平台的构建系统生成工具,在Linux环境下使用CMake来构建C/C++项目时,使用CMakeLists.txt实现项目快速构建。下面使用CMake命令构建项目:

1. 构建一个简单项目的CMakeLists.txt

对于以下简单的项目目录

├── CMakeLists.txt
└── test.cpp

CMakeLists.txt内容如下

cmake_minimum_required(VERSION 3.10)
project(test LANGUAGES C CXX)
add_executable(test_project test.cpp)
  • cmake_minimum_required用于指定本项目CMake的最低版本要求,如果CMake的版本低于指定的版本要求,则会报错。

  • project定义项目的名称和语言,MyProject是项目的名称,它会被赋值给cmake的预定义变量 ${PROJECT_NAME},并且可以在整个 CMakeLists.txt 文件中使用这个变量来引用项目名称。LANGUAGES C CXX表示项目使用的编程语言。在这个例子中,表示项目使用C和C++语言。

  • add_executable: 添加源文件和目标并生成一个可执行文件,并指定该可执行文件的所有源文件列表,如果源文件过多,推荐使用

    aux_source_directory(. SRC_LIST)
    add_executable(test_project ${SRC_LIST})
    
  • aux_source_directory表示将当前路径的所有源文件列表添加到SRC_LIST变量中,就可以使用${SRC_LIST}作为add_executable的源文件列表。

2. 生成可执行文件
  • 在当前目录创建build文件夹,原因是cmake可以直接使用上一级目录的CMakeLists.txt自动生成Makefile,这样能够保证生成的文件不会与源文件混在一起,此时目录和CMakeLists.txt如下

    ├── build
    ├── CMakeLists.txt
    └── test.cpp
    
    cmake_minimum_required(VERSION 3.1)
    project(test LANGUAGES C CXX)
    aux_source_directory(. SRC_LIST)
    add_executable(test_project ${SRC_LIST})
    
  • 在build目录下执行cmake,构建系统文件

    cmake ..
    
  • 再使用make命令自动编译源代码、链接库文件,并生成当前文件或库

    make
    
  • 构建成功后,在build目录如下
    ├── CMakeCache.txt
    ├── CMakeFiles
    ├── cmake_install.cmake
    ├── Makefile
    └── test_project

  • test_project是生成的可执行文件,能够直接运行

3. 多级目录项目构建

在实际项目中,通常会将项目分成多个目录,每个目录包含一个或多个源文件和头文件,通常需要每个目录都有一个CMakeLists.txt文件,在Ubuntu环境,例如有如下嵌套型的目录结构:

└── test
    ├── CMakeLists.txt
    ├── example
    │   ├── CMakeLists.txt
    │   ├── demo
    │   │   ├── CMakeLists.txt
    │   │   ├── demo.cpp
    │   │   └── demo.hpp
    │   ├── example.cpp
    │   └── example.hpp
    ├── include
    │   ├── CMakeLists.txt
    │   ├── detail.cpp
    │   └── detail.hpp
    └── test.cpp
  • 对于内层的目录test/example/demo/CMakeLists.txt如下:

    aux_source_directory(. t_SRCS)
    add_library(demo ${t_SRCS})
    
  • aux_source_directory命令来获取源文件列表,然后使用add_library创建一个库,add_library一般有动态库和静态库两种形式,STATIC表示生成静态库,SHARED表示生成动态库(默认为静态库):

    • add_library(库名 STATIC 源文件列表)
    • add_library(库名 SHARED 源文件列表)
  • 对于外层的目录test/example/CMakeLists.txt如下,:

    aux_source_directory(. SRCS)
    aux_source_directory(demo DEMO_SRCS)
    include_directories(demo)
    add_library(example ${SRCS} ${DEMO_SRCS})
    
  • 除了包含example目录的源文件外,需要再将子目录demo加到变量中,使用include_directories指定编译器在编译源文件时搜索头文件的路径(仅影响项目路径,不影响生成的构建目标),最后使用add_library生成一个当前目录的库。

  • 同样,对于test/include/CMakeLists.txt如下:

    aux_source_directory(. SRCS)
    add_library(include ${SRCS})
    
  • test/CMakeLists.txt如下:

    cmake_minimum_required(VERSION 3.1)
    project(test)
    aux_source_directory(. SRC_LIST)
    add_subdirectory(example)
    add_subdirectory(include)
    add_executable(test_project ${SRC_LIST})
    target_link_libraries(test_project example include)
    
  • 使用add_subdirectory命令向当前工程添加存放源文件的子目录example和include,并在指定的子目录中查找 CMakeLists.txt文件,并将其内容包含到当前构建中

  • 最后需要使用target_link_libraries,为目标文件链接库文件,稍大型项目需要注意链接顺序,一般为:直接依赖库-间接依赖库-系统库

  • 在build目录下进行构建,结果如下:
    在这里插入图片描述
    成功运行

4. 添加编译选项

项目中会有添加编译选项需求,如指定语言版本,设置编译器调试标志,设置交叉编译等,可以通过指定语句添加,也可通过SET命令定义或修改变量和cmake的预定义变量实现,SET用法:

SET(VARIABLE_NAME value)
  • SET与预定义变量结合示例:

    set(CROSS_COMPILE ON)
    set(CMAKE_SYSTEM_NAME Linux)
    
  • 表示开启交叉编译,并指定当前系统为Linux

    SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g")
    
  • 设置调试标志,$ENV{CXXFLAGS}是从环境变量中获取现有的CXXFLAGS,-O0表示关闭所有优化,-Wall表示启用所有常见的警告信息,-g表示生成调试信息

以下给出一些常用的预定义变量:

CMAKE_SOURCE_DIR:根CMakeLists.txt所在的目录路径。
CMAKE_BINARY_DIR:构建目录的路径。
PROJECT_SOURCE_DIR:当前项目的根目录路径。
PROJECT_BINARY_DIR:当前项目的构建目录路径。
CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt所在的目录路径。
CMAKE_CURRENT_BINARY_DIR:当前处理的构建目录路径。
CMAKE_COMMAND:CMake可执行文件的完整路径。
CMAKE_C_COMPILER:C编译器的路径。
CMAKE_CXX_COMPILER:C++编译器的路径。
CMAKE_BUILD_TYPE:构建类型(如Debug、Release)。
CMAKE_SYSTEM_NAME:系统名称(如Linux、Windows)。
CMAKE_SIZEOF_VOID_P:指针大小(用于判断32位或64位)。

  • cmake中同样可以使用if else和比较运算符用于条件判断,可以与预定义变量结合使用,基本用法如下:

    set(VALUE 10)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
        message("message")
    elseif(VALUE GREATER 5)
        message("VALUE is greater than 5")
    else()
        message("VALUE is less than or equal to 5")
    endif()
    

推荐一个c/c++内容学习平台

https://github.com/0voice

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值