一、一个典型CMakeLists.txt都包含哪些部分?
👉 标准结构如下:
1. 基本信息
cmake_minimum_required(...)
project(...)
完整示例(推荐):
project(SoC_Sim
VERSION 1.0
DESCRIPTION "SystemC SoC Simulation Platform"
LANGUAGES CXX
)
2. 全局配置
set(...)
option(...)
3. 依赖查找
find_package(...)
include_directories(...)
link_directories(...)
target_include_directories(...)
4. 源码组织
add_library(...)
add_executable(...)
5. 链接关系
target_link_libraries(...)
6. 编译选项
target_compile_options(...)
target_compile_definitions(...)
7. 子模块
add_subdirectory(...)
8. 安装/导出(可选)
install(...)
二、逐块解释
1️⃣ 基本信息(必须有)
cmake_minimum_required(VERSION 3.16)
project(SoC_Sim)
👉 作用:
cmake_minimum_required(VERSION <min>[...<policy_max>]):
"这个工程至少需要这个版本的 CMake 才能正确构建"。
project(<name>
VERSION \
DESCRIPTION \
LANGUAGES \
<lib1> <lib2> ...
)
真正关键:三种作用域(核心🔥)
PRIVATE
target_link_libraries(memory PRIVATE systemc)
👉 含义:
memory 自己用 systemc,但不会传递给别人
PUBLIC
target_link_libraries(memory PUBLIC systemc)
👉 含义:
memory 用 systemc,并且依赖它的人也必须用
INTERFACE
target_link_libraries(soc_core INTERFACE memory)
👉 含义:
自己不用,但使用它的人必须用
推荐写法(标准):
memory模块
add_library(memory ddr_ctrl.cpp)
target_link_libraries(memory
PUBLIC systemc
)
noc模块
add_library(noc router.cpp)
target_link_libraries(noc
PUBLIC systemc
)
聚合
add_library(soc_core INTERFACE)
target_link_libraries(soc_core
INTERFACE memory noc
)
仿真顶层
add_executable(sim tb_top.cpp)
target_link_libraries(sim
soc_core
m
)
依赖传播结果:
sim
└── soc_core
├── memory
│ └── systemc
└── noc
└── systemc
👉 sim 自动拥有:
- systemc
- memory
- noc
常见错误
❌ 1. 全用 PRIVATE
target_link_libraries(memory PRIVATE systemc)
👉 结果:
sim 找不到 systemc ❌
❌ 2. 不用 INTERFACE 聚合
target_link_libraries(sim memory noc systemc)
👉 问题:
- sim 依赖过多
- 层次混乱
❌ 3. 顺序错误(老编译器)
target_link_libraries(sim systemc memory) ❌
👉 有些平台会炸
6️⃣ 编译选项(调试/优化)
target_compile_options(sim PRIVATE -O2 -Wall)
语法:
target_compile_options(<target>
PRIVATE \| PUBLIC \| INTERFACE
<options...>
)
它在干什么?
👉 本质:
给编译器加参数(类似 g++ 后面的 -O2 -Wall)
示例
target_compile_options(sim PRIVATE -O2 -Wall)
👉 等价:
g++ -O2 -Wall ...
常见选项
target_compile_options(sim PRIVATE
-O2 # 优化
-g # 调试信息
-Wall # 警告
-Wextra
)
作用域(和 link 一样🔥)
PRIVATE
target_compile_options(memory PRIVATE -O2)
👉 只影响 memory 自己
PUBLIC
target_compile_options(memory PUBLIC -O2)
👉 memory 和依赖它的模块都会用
INTERFACE
target_compile_options(soc_core INTERFACE -O2)
👉 自己不用,但下游会用
7️⃣ 宏定义(非常有用)
语法:
target_compile_definitions(<target>
PRIVATE \| PUBLIC \| INTERFACE
<definitions...>
)
target_compile_definitions(sim PRIVATE DEBUG=1)
👉 类似 RTL:
`define DEBUG
结合 option 使用(工程级)
示例:
cmake:
option(ENABLE_TRACE "Enable waveform" ON)
if(ENABLE_TRACE)
target_compile_definitions(sim PRIVATE ENABLE_TRACE)
endif()
c++:
#ifdef ENABLE_TRACE
dump_wave();
#endif
8️⃣ 子目录(大项目必备)
add_subdirectory(src)
add_subdirectory(tb)
add_subdirectory(noc)
👉 用于:
-
分模块管理
-
团队协作
-
👉
add_subdirectory(...)的本质是:
"把子目录的 CMakeLists.txt 纳入当前工程,并参与构建"
基本语法
add_subdirectory(<source_dir> [binary_dir] [EXCLUDE_FROM_ALL])
参数解释
🔹
<source_dir>(必须)add_subdirectory(src)👉 表示:
进入 src/ 目录,执行里面的 CMakeLists.txt
🔹
[binary_dir](可选)add_subdirectory(src build_src)👉 指定这个子目录的构建输出目录
👉 很少用,一般不用写
🔹
[EXCLUDE_FROM_ALL](高级)add_subdirectory(test EXCLUDE_FROM_ALL)
👉 表示:
默认不参与构建(除非被依赖)
它到底干了什么?
当你写:
add_subdirectory(src)
👉 实际发生:
- 进入 src/CMakeLists.txt
- 执行里面所有 add_library / add_executable
- 把这些 target 注册到整个工程
9️⃣ 安装(一般后期才用)
install(TARGETS sim DESTINATION bin)
👉
install(...)解决的是:"别人怎么用你的工程"
先给一句本质:
👉
install(...)的本质是:
"定义构建完成后,文件要被拷贝到哪里、以什么结构对外发布"
基本语法(常见形式):
install(TARGETS ...)
install(FILES ...)
install(DIRECTORY ...)
install(EXPORT ...)
👉 这四个就是你 90% 会用到的
最核心:install(TARGETS ...)
语法
install(TARGETS <targets...>
RUNTIME DESTINATION <dir> # 可执行文件
LIBRARY DESTINATION <dir> # 动态库
ARCHIVE DESTINATION <dir> # 静态库
)
示例
add_executable(sim tb_top.cpp)
install(TARGETS sim
RUNTIME DESTINATION bin
)
👉 安装后:
install_prefix/
└── bin/
└── sim
库安装
add_library(memory STATIC ddr_ctrl.cpp)
install(TARGETS memory
ARCHIVE DESTINATION lib
)
👉 生成:
lib/libmemory.a
安装头文件(非常重要)
install(FILES ...)
install(FILES
include/ddr_ctrl.h
DESTINATION include
)
install(DIRECTORY ...)(推荐)
install(DIRECTORY include/
DESTINATION include
)
👉 会保留目录结构
安装完整工程结构(标准做法)
推荐结构
install(TARGETS memory noc
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
install(DIRECTORY include/
DESTINATION include
)
👉 安装后:
install_prefix/
├── lib/
│ ├── libmemory.a
│ └── libnoc.a
└── include/
├── ddr_ctrl.h
└── noc.h
install(EXPORT ...)(高级🔥)
👉 这是配合 find_package 的关键
语法
install(EXPORT <export_name>
DESTINATION lib/cmake/<PackageName>
)
示例
install(TARGETS memory noc
EXPORT SoCTargets
)
install(EXPORT SoCTargets
DESTINATION lib/cmake/SoC
)
👉 作用:
生成:
SoCTargets.cmake
👉 这样别人可以:
find_package(SoC)
target_link_libraries(app SoC::memory)
安装路径控制
默认路径
cmake --install .
👉 默认安装到:
/usr/local
自定义路径
cmake -DCMAKE_INSTALL_PREFIX=./install ..
cmake --build .
cmake --install .
👉 安装到:
./install/