CMakeLists中 get_filename_component详解

get_filename_component是 CMake 中用于路径处理的核心指令,主要作用是提取当前源码目录的上级目录路径并赋值给指定变量。

当我们使用的命令是

get_filename_component(PACKAGE_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} PATH)

假设你的项目目录结构如下:

plaintext 复制代码
  
/my_project/                # 根目录(我们要获取的目标目录)
├── src/                    # 子目录
│   └── module/             # 子子目录(当前 CMakeLists.txt 所在目录)
│       └── CMakeLists.txt  # 执行这行代码的文件
└── include/
 

此时:

  • CMAKE_CURRENT_SOURCE_DIR 的值是 /my_project/src/module ;
  • 执行 get_filename_component(PACKAGE_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} PATH) 后;
  • PACKAGE_SOURCE_ROOT 的值是 /my_project/src (即当前目录的上级目录)。

如果想获取根目录( /my_project ),可以嵌套执行:

cmake 复制代码
  
# 第一步:拿到 /my_project/src
get_filename_component(PACKAGE_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} PATH)
# 第二步:拿到 /my_project(再往上一级)
get_filename_component(PACKAGE_SOURCE_ROOT ${PACKAGE_SOURCE_ROOT} PATH)
message(STATUS "PACKAGE_SOURCE_ROOT = ${PACKAGE_SOURCE_ROOT}")
# 输出:-- PACKAGE_SOURCE_ROOT = /my_project
 

现代替代写法(CMake 3.20+)

CMake 3.20 及以上版本提供了更直观的 cmake_path 指令,功能等价且可读性更好,推荐优先使用:

cmake 复制代码
  
# 等价于原代码:提取上级目录
cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH PACKAGE_SOURCE_ROOT)
# 如果要提取多级上级目录(比如两级),可以这样写:
cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH temp_dir)
cmake_path(GET temp_dir PARENT_PATH PACKAGE_SOURCE_ROOT)

常见使用场景

  1. 统一引用上级目录的文件:比如当前子目录的 CMakeLists.txt 需要引用上级目录的 include 文件夹、配置文件等,通过这个变量可以避免写死相对路径(如 .../.../include ),提升代码可移植性。
cmake 复制代码
  
# 获取上级目录
get_filename_component(PACKAGE_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR} PATH)
# 引用上级目录的 include 文件夹
include_directories(${PACKAGE_SOURCE_ROOT}/include)
  1. 定位项目根目录:通过多次提取上级目录,最终定位到项目根目录,方便统一管理资源、库文件等。
  2. 避免硬编码路径:相比直接写 .../ 这种相对路径,用 get_filename_component 更清晰,且能自动处理不同系统的路径分隔符(Windows 的 \ 和 Linux/macOS 的 / )。

总结

  1. 核心作用: get_filename_component(变量 路径 PATH) 是提取指定路径的上级目录,并赋值给变量,等价于 dirname 命令。
  2. CMAKE_CURRENT_SOURCE_DIR 是当前 CMakeLists.txt 所在的源码目录,结合 PATH 参数就能拿到它的父目录。
  3. 现代写法(CMake 3.20+)推荐用 cmake_path(GET ... PARENT_PATH ...) ,语义更清晰,路径处理更健壮。
相关推荐
熊猫钓鱼>_>4 分钟前
三方库 NDK 原生模块跨平台适配与调试【鸿蒙心迹】
开发语言·华为·ai编程·harmonyos·鸿蒙·openharmony·鸿蒙心迹
HANDY0920010 分钟前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
1024奇点9 小时前
【仓颉语言入门 · 第二篇 第 22 课】
开发语言·ide·开源
Warren2Lynch10 小时前
C4 模型详解:利用 Visual Paradigm 可视化软件架构的综合指南
开发语言·uml
Knight_AL11 小时前
Java 文件下载时文件名中的 `#` 被转换成 `%23`?一次 URL 编码与解码问题排查
java·开发语言
FRing0311 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
by2099912 小时前
C++ 智能指针的所有权与使用
开发语言·c++·经验分享
砚底藏山河12 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
IT召唤狮12 小时前
开源企业级零信任项目Pangolin,零信任能挡住PHP核弹漏洞吗?
开发语言·开源·php
知已难寻12 小时前
03 · OpenStack的计算管理 Nova
运维·服务器·开发语言·云原生·云计算·openstack·开源软件