CMake CMakeLists

本文详细介绍了如何使用CMake组织项目编译框架,包括目录结构布局、定义输出目标(如可执行程序、动态库和静态库)、指定编译与链接参数等内容。适合初学者和进阶用户参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考 Cmake实战指南 CMakeLists.txt 语法介绍与实例

[TOC]

  • 怎么去 组织一个项目的编译框架
  • 最终 输出目标 有哪些(可执行程序,动态库,静态库等等)
  • 怎么为指定的输出目标指定编译参数(需要哪些源文件,需要哪些编译参数)
  • 怎么为指定的输出目标指定链接参数(需要哪些外部库,需要哪些链接参数)
  • 如果存在多个独立输出目标是否有执行先后顺序(比如项目有自动配置工具,用来自动生产一些源文件,那么自动配置工具输出目标就要先于其他目标比如输出可执行程序目标)

一、组织项目的编译框架

  • 目录结构
├── CMakeLists.txt      // 根目录放置一个CMakeLists.txt
├── arch
│   └── CMakeLists.txt  // 每个需要管理的目录下面也放置一个CMakeLists.txt
├── cfg
│   └── CMakeLists.txt
├── doc
│   └── CMakeLists.txt
├── drivers
│   └── CMakeLists.txt
├── fs
│   └── CMakeLists.txt
├── include // 头文件cmake会自动去构建不需要通过CMakeLists.txt手动添加
├── kernel
│   └── CMakeLists.txt
├── library
│   └── CMakeLists.txt
├── sample
│   └── CMakeLists.txt
└── utils
│   └── CMakeLists.txt
├── cmake   // 用来放置通用的cmake源码模块(如:通用编译环境设置,编译链接的一些选项配置...)
├── build   // 存放项目构建过程中所有的输出文件
  • 根目录下面CMakeLists.txt
#cmake最低版本要求
cmake_minimum_required(VERSION 3.10.0)

#项目名字为test
project(test NONE)

#包含通用的编译环境模块到顶层目录
include(${CMAKE_SOURCE_DIR}/cmake/base.cmake)

#下一级的编译目录
add_subdirectory(arch)
add_subdirectory(cfg)
add_subdirectory(doc)
add_subdirectory(drivers)
add_subdirectory(fs)
add_subdirectory(kernel)
add_subdirectory(library)
add_subdirectory(sample)
add_subdirectory(utils)
命令标签格式说明
cmake_minimum_required(VERSION major.minor[.patch[.tweak]] [FATAL_ERROR])设置最低版本的cmake要求(一般放在第一行)
project( [LANGUAGES] […])设置项目名,版本,启用的编程语言,上面没有启用任何编程语言所以用NONE
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])增加一个子目录到编译系统
include(<file|module> [OPTIONAL] [RESULT_VARIABLE ][NO_POLICY_SCOPE])从给出的file文件加载和运行cmake代码

二、最终输出目标

  • 编译器编译链接之后产生的最终结果(linux下面的elf文件,.a静态库,.so的动态库)
  • 主要通过add_executable来定义输出可执行程序目标,
    主要通过add_library来定义输出动态库,静态库,模块等目标。
  • 定义的输出目标是全局的,比如你在根目录通过add_executable定义了一个输出目标,可以在子目录中用target_sources命令往这个输出目标里面加源文件,cmake在输出这个目标之前会在当前project中搜集所有添加到该目标的源文件再去生成一个编译链接的规则
#定义一个mytool 可执行程序输出目标,目前只有一个源文件  mytool.cpp
add_executable(mytool mytool.cpp)

#往mytool可执行程序输出目标添加源文件,现在mytool目标里面包含两个源文件
target_sources(mytool  PRIVATE mytool2.cpp)

#定义一个动态库archive 输出目标,文件有三个源文件
add_library(archive SHARED archive.cpp zip.cpp lzma.cpp)

#定义一个静态库archive 输出目标,也可以不指定STATIC 因为add_library默认输出目标是#静态库
add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)

#从给出的源文件直接生成object文件,比如linux下C语言的.o文件
add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)
命令标签格式说明
add_executable( [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 …])定义一个名字为name可执行程序输出目标,其中 source1 [source2 …]是源文件,比如C语言是.C的源文件,.H的源文件不需要指定,cmake会自动去搜索
add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 …]) add_library( OBJECT …)定义一个名字为name的库输出目标
target_sources(<INTERFACE|PUBLIC|PRIVATE> [items1…][<INTERFACE|PUBLIC|PRIVATE> [items2…] …])往一个目标里面添加源文件,这个目标名字target是在add_executable() 或者add_library() 中定义的name
  • 如果源文件(例如CPP)中包含第三方头文件,但是头文件(例如hpp)中不包含该第三方文件头,采用PRIVATE
  • 如果源文件和头文件中都包含该第三方文件头,采用PUBLIC
  • 如果头文件中包含该第三方文件头,但是源文件(例如CPP)中不包含,采用 INTERFACE

三、指定编译参数和链接参数

  • add_executable()或者add_library()中定义的输出目标指定编译选项可以通过下面3个命令函数;
命令标签格式说明
row 1 col 1row 1 col 2
row 2 col 1row 2 col 2
# gcc头文件查找目录,相当于-I选项,e.g -I/foo/bar
#CMAKE_SOURCE_DIR是cmake内置变量表示当前项目根目录
target_include_directories(test_elf
    PRIVATE
    ${CMAKE_SOURCE_DIR}
    ${CMAKE_SOURCE_DIR}/common
    ${CMAKE_SOURCE_DIR}/syscalls
)

# 编译的宏定义,e.g 相当于-D选项 e.g -Dmacro=defn
set(MONITOR_OMIT_BSS_INIT      "0")
set(MONITOR_OMIT_DATA_INIT     "0")
set(MONITOR_OMIT_T_CHECKS      "0")
target_compile_definitions(test_elf
    PRIVATE
    MONITOR_OMIT_BSS_INIT=${MONITOR_OMIT_BSS_INIT}              
    MONITOR_OMIT_DATA_INIT=${MONITOR_OMIT_DATA_INIT}            
    MONITOR_TRAP_NT_IRQS=${MONITOR_TRAP_NT_IRQS}                          
)

# 其他编译选项定义,e.g -fPIC
target_compile_options(test_elf
    PRIVATE
    -std=c99 
    -Wall 
    -Wextra 
    -Werror
)
### CMakeLists.txt 的基本配置与语法说明 CMake 是一种跨平台的构建工具,通过 `CMakeLists.txt` 文件定义项目结构和编译规则。以下是关于如何编写或配置 `CMakeLists.txt` 文件的具体方法及其常用语法。 #### 1. 定义项目名称 使用 `project()` 函数来指定项目的名称以及支持的语言类型。例如,在一个简单的 Hello World 工程中可以这样设置: ```cmake project(HELLO) ``` 这表示当前项目名为 HELLO[^1]。 #### 2. 添加可执行文件 通过 `add_executable()` 来声明生成的目标程序,并指明所需的源文件。如果有一个名为 `main.c` 的源文件,则可以在 `CMakeLists.txt` 中加入如下语句: ```cmake add_executable(hello main.c) ``` 此命令告诉 CMake 将 `main.c` 编译成名为 `hello` 的可执行文件。 #### 3. 构建过程中的目录管理 为了保持源码目录整洁,推荐在一个单独的子目录下完成构建操作。具体做法是在项目根路径创建一个新的文件夹(比如叫 `build`),进入该文件夹运行 CMake 和 Make 命令即可实现无污染编译环境的目的。典型的操作序列如下所示: ```bash mkdir build && cd build cmake .. make ``` 上述脚本先建立并切换到 `build` 子目录,接着调用父级目录里的 `CMakeLists.txt` 自动生成相应平台下的构建体系描述文档(如 Unix 下面就是 Makefile)。最后一步则是依据前面产生的这些中间产物实际启动整个软件包组装流水线工作流[^2][^3]。 #### 4. 更复杂的例子——多文件项目 对于稍微复杂一点的情况来说,假设我们的应用程序由多个模块构成,那么就需要分别引入它们各自的头文件位置还有库链接关系等内容项了。下面给出一段示范性的代码片段作为参考: ```cmake # 设置最低版本需求 cmake_minimum_required(VERSION 3.0) # 初始化工程名 project(MyProject LANGUAGES CXX) # 指定额外包含路径 include_directories(include) # 创建目标二进制文件 add_executable(myapp src/main.cpp src/utils.cpp) # 如果存在外部依赖则需添加此处省略部分... target_link_libraries(myapp PRIVATE some_library) ``` 以上展示了更完整的场景应用案例,其中包含了设定最小兼容版号、启用特定编程语言特性集等功能扩展点;同时还演示了怎样向编译器传递附加搜索范围参数以便于找到自定义或者第三方提供的接口定义资料所在之处;另外还涉及到了最终环节里边有关连接阶段处理逻辑方面的安排事项等等。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值