天水市网站建设_网站建设公司_测试上线_seo优化
2026/1/10 4:21:47 网站建设 项目流程

目录

1.简介

2.最常用的 5 种解析模式

2.1.DIRECTORY

2.2.NAME

2.3.NAME_WE (Name Without Extension)

2.4.EXT

2.5.ROOT

3.使用场景

3.1.多级路径向上推导(写XXXConfig.cmake必用)

3.2.规范化路径(去除./../,转为绝对路径)

3.3.提取文件名 + 后缀分离

3.4.配合CMAKE_CURRENT_LIST_DIR拼接路径

4.注意事项

5.完整可复用:自定义XXXConfig.cmake中的路径推导模板


1.简介

CMake进阶:vcpkg中OpenSSLConfig.cmake详解

get_filename_componentCMake 内置核心命令(不是变量),也是实现「第三方库路径自动推导」的核心,专门用于解析 / 提取文件路径、目录路径、文件名、后缀名等路径相关信息,是实现跨平台路径处理、编写通用XXXConfig.cmake/CMakeLists.txt的必备命令,没有之一。

语法:

get_filename_component(<输出变量名> <待解析的路径> <解析模式> [ABSOLUTE] [REALPATH])

参数说明:

  • <输出变量名>:解析后的结果,存入这个变量中供后续使用;
  • <待解析的路径>:可以是文件路径目录路径,支持相对路径 / 绝对路径;
  • <解析模式>:核心!指定要解析的内容,大小写不敏感,有 7 种常用模式,重点记前 5 个高频的
  • [ABSOLUTE]:可选但几乎必加!将解析后的相对路径转为绝对路径,CMake 路径处理推荐一律用绝对路径,避免各种路径错误;
  • [REALPATH]:可选,解析出真实路径(会解析软链接 / 快捷方式、去除路径中的.//../),跨平台兼容性更强。

2.最常用的 5 种解析模式

2.1.DIRECTORY

提取传入路径对应的上级目录路径文件 / 目录路径都能解析

  • 如果传入的是「文件路径」→ 提取该文件所在的目录
  • 如果传入的是「目录路径」→ 提取该目录的上级目录
以目录 D:/project/thirdparty/xxx/lib/cmake/xxx/XXXConfig.cmake 为例: # 示例:传入 配置文件的绝对路径 (${CMAKE_CURRENT_LIST_FILE}就是当前脚本自身路径) get_filename_component(CONFIG_DIR ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) # 结果:CONFIG_DIR = D:/project/thirdparty/xxx/lib/cmake/xxx # 简写PATH 和 DIRECTORY 完全等价,推荐写DIRECTORY语义更清晰 get_filename_component(CONFIG_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)

2.2.NAME

提取传入路径的「文件名」(包含后缀),不管传入的是文件还是目录

get_filename_component(FILE_NAME ${CMAKE_CURRENT_LIST_FILE} NAME) # 结果:FILE_NAME = XXXConfig.cmake # 如果传入目录路径 get_filename_component(DIR_NAME "D:/project/thirdparty/xxx/lib" NAME) # 结果:DIR_NAME = lib

2.3.NAME_WE(Name Without Extension)

提取文件名不含后缀,仅对文件路径有效,目录路径用这个无意义

get_filename_component(FILE_NAME_NO_EXT ${CMAKE_CURRENT_LIST_FILE} NAME_WE) # 结果:FILE_NAME_NO_EXT = XXXConfig

2.4.EXT

提取文件的后缀名(带.),仅对文件路径有效

get_filename_component(FILE_EXT ${CMAKE_CURRENT_LIST_FILE} EXT) # 结果:FILE_EXT = .cmake

2.5.ROOT

提取路径的根目录,比如 Windows 的D:/,Linux/macOS 的/

get_filename_component(ROOT_DIR ${CMAKE_CURRENT_LIST_FILE} ROOT) # Windows结果:ROOT_DIR = D:/ # Linux/macOS结果:ROOT_DIR = /

3.使用场景

3.1.多级路径向上推导(写XXXConfig.cmake必用)

在自定义XXXConfig.cmake中,通过「配置文件自身路径」自动向上推导整个库的根目录、头文件目录、库文件目录、bin 目录无需硬编码任何路径,实现「库放在任意位置都能被 CMake 自动识别」,也是所有官方XXXConfig.cmake的标准写法。

你的XXXConfig.cmake的标准存放路径:

thirdparty/xxx/ # 库的根目录(我们最终要推导的) ├── include/ # 头文件目录(需要推导) ├── lib/ # 库文件目录(需要推导) │ └── cmake/ │ └── xxx/ # 库名目录 │ └── XXXConfig.cmake # 当前脚本自身 └── bin/ # DLL/SO动态库目录(需要推导)

核心目标:在XXXConfig.cmake中,从脚本自身路径出发,推导出上面所有目录,完全无硬编码

# 1. 获取当前XXXConfig.cmake脚本自身的绝对路径(CMAKE_CURRENT_LIST_FILE是脚本自身路径) # 路径:thirdparty/xxx/lib/cmake/xxx/XXXConfig.cmake get_filename_component(_XXX_CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY ABSOLUTE) # 2. 向上1级 → cmake/xxx 目录 # 路径:thirdparty/xxx/lib/cmake/xxx get_filename_component(_XXX_CMAKE_SUB_DIR "${_XXX_CONFIG_DIR}" DIRECTORY ABSOLUTE) # 3. 向上1级 → cmake 目录 # 路径:thirdparty/xxx/lib/cmake get_filename_component(_XXX_CMAKE_DIR "${_XXX_CMAKE_SUB_DIR}" DIRECTORY ABSOLUTE) # 4. 向上1级 → lib 目录 # 路径:thirdparty/xxx/lib get_filename_component(_XXX_LIB_DIR "${_XXX_CMAKE_DIR}" DIRECTORY ABSOLUTE) # 5. 向上1级 → 库的根目录【最终核心】 # 路径:thirdparty/xxx get_filename_component(_XXX_ROOT_DIR "${_XXX_LIB_DIR}" DIRECTORY ABSOLUTE) # ✅ 最终:通过根目录,拼接出所有需要的目录,固定写法,永不失效 set(_XXX_INCLUDE_DIR "${_XXX_ROOT_DIR}/include") # 头文件目录 set(_XXX_BIN_DIR "${_XXX_ROOT_DIR}/bin") # 动态库运行目录 set(_XXX_LIB_DIR "${_XXX_ROOT_DIR}/lib") # 静态/导入库目录

3.2.规范化路径(去除./../,转为绝对路径)

有时候路径中会有./../,导致路径不规范,用get_filename_component+ABSOLUTE+REALPATH可以一键规范化:

# 原始路径有../,不规范 set(RAW_PATH "./thirdparty/../xxx/lib") # 规范化为绝对路径,去除../ get_filename_component(NORMAL_PATH ${RAW_PATH} DIRECTORY ABSOLUTE REALPATH)

3.3.提取文件名 + 后缀分离

处理配置文件、源码文件时常用:

set(FILE_PATH "D:/project/src/main.cpp") get_filename_component(FILE_NAME ${FILE_PATH} NAME) # main.cpp get_filename_component(FILE_NAME_WE ${FILE_PATH} NAME_WE) # main get_filename_component(FILE_EXT ${FILE_PATH} EXT) # .cpp

3.4.配合CMAKE_CURRENT_LIST_DIR拼接路径

和之前CMAKE_CURRENT_LIST_DIR完美配合,实现跨平台路径拼接:

# 拼接当前脚本同级的config目录 get_filename_component(CONFIG_DIR "${CMAKE_CURRENT_LIST_DIR}/config" DIRECTORY ABSOLUTE)

4.注意事项

1.DIRECTORYPATH完全等价

CMake 官方定义,这两个模式是同一个意思,推荐写DIRECTORY,语义更清晰,一眼看出是「提取目录」。

2.强烈建议永远加上ABSOLUTE参数

CMake 中路径分「相对路径」和「绝对路径」,相对路径容易因为CMAKE_CURRENT_SOURCE_DIR/CMAKE_CURRENT_BINARY_DIR的变化导致路径错误,所有路径处理都用绝对路径,是 CMake 的最佳实践。

3.路径分隔符自动跨平台兼容

get_filename_component会自动适配 Windows 的\和 Linux/macOS 的/,你在代码中写/即可,CMake 会自动转换为对应系统的分隔符,无需手动处理。

4.变量名建议加下划线前缀(私有变量)

推导路径时的临时变量(比如_XXX_CONFIG_DIR_XXX_ROOT_DIR),建议加下划线前缀,表示这是脚本内的私有变量,避免和外部用户定义的变量重名冲突,这是 CMake 官方的编码规范。

5.多级推导的顺序不能乱

向上推导目录时,必须从脚本自身路径开始,逐级向上,不能跳过层级,否则会推导错误。

5.完整可复用:自定义XXXConfig.cmake中的路径推导模板

# ============================================================================== # XXXConfig.cmake 通用路径推导模板 (替换XXX为你的库名) # 配置文件路径:xxx/lib/cmake/xxx/XXXConfig.cmake # ============================================================================== # 1. 从脚本自身路径,逐级向上推导库根目录 get_filename_component(_XXX_CONFIG_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY ABSOLUTE) get_filename_component(_XXX_LIB_CMAKE_DIR "${_XXX_CONFIG_DIR}" DIRECTORY ABSOLUTE) get_filename_component(_XXX_LIB_DIR "${_XXX_LIB_CMAKE_DIR}" DIRECTORY ABSOLUTE) get_filename_component(_XXX_ROOT_DIR "${_XXX_LIB_DIR}" DIRECTORY ABSOLUTE) # 2. 定义库的核心目录(固定写法) set(XXX_INCLUDE_DIRS "${_XXX_ROOT_DIR}/include" CACHE PATH "XXX头文件目录") set(XXX_LIBRARY_DIRS "${_XXX_ROOT_DIR}/lib" CACHE PATH "XXX库文件目录") set(XXX_BIN_DIR "${_XXX_ROOT_DIR}/bin" CACHE PATH "XXX动态库运行目录") set(XXX_ROOT_DIR "${_XXX_ROOT_DIR}" CACHE PATH "XXX库根目录") # 3. 验证目录存在性(报错提示,可选但推荐) if(NOT EXISTS ${XXX_INCLUDE_DIRS}) message(FATAL_ERROR "XXX头文件目录不存在: ${XXX_INCLUDE_DIRS}") endif() if(NOT EXISTS ${XXX_LIBRARY_DIRS}) message(FATAL_ERROR "XXX库文件目录不存在: ${XXX_LIBRARY_DIRS}") endif()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询