CMake 提供了许多有用的目录相关宏变量,用于在不同平台上正确处理文件路径。以下是完整的分类说明:
- 标准目录变量
系统标准目录
cmake
安装目录变量
CMAKE_INSTALL_PREFIX # 安装根目录 (/usr/local)
CMAKE_INSTALL_BINDIR # 可执行文件目录 (bin)
CMAKE_INSTALL_SBINDIR # 系统可执行文件目录 (sbin)
CMAKE_INSTALL_LIBDIR # 库文件目录 (lib 或 lib64)
CMAKE_INSTALL_INCLUDEDIR # 头文件目录 (include)
CMAKE_INSTALL_DATAROOTDIR # 数据文件根目录 (share)
CMAKE_INSTALL_DATADIR # 数据文件目录 (share)
CMAKE_INSTALL_DOCDIR # 文档目录 (share/doc)
CMAKE_INSTALL_MANDIR # man 手册目录 (share/man)
CMAKE_INSTALL_SYSCONFDIR # 配置文件目录 (etc)
CMAKE_INSTALL_LOCALSTATEDIR # 本地状态数据目录 (var)
使用示例
cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 设置安装路径
set(CMAKE_INSTALL_PREFIX "/opt/myapp")
# 安装目标
install(TARGETS myapp
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(FILES myheader.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/myproject
)
install(DIRECTORY docs/
DESTINATION ${CMAKE_INSTALL_DOCDIR}
)
- 项目目录变量
项目相关目录
cmake
项目根目录
CMAKE_SOURCE_DIR # 顶层 CMakeLists.txt 所在目录
CMAKE_BINARY_DIR # 构建根目录 (build)
CMAKE_CURRENT_SOURCE_DIR # 当前处理的 CMakeLists.txt 所在目录
CMAKE_CURRENT_BINARY_DIR # 当前构建目录
CMAKE_CURRENT_LIST_DIR # 当前正在处理的 CMake 文件所在目录
项目特定目录
PROJECT_SOURCE_DIR # 项目 CMakeLists.txt 目录
PROJECT_BINARY_DIR # 项目构建目录
<PROJECT-NAME>_SOURCE_DIR # 特定项目源码目录
<PROJECT-NAME>_BINARY_DIR # 特定项目构建目录
使用示例
cmake
cmake_minimum_required(VERSION 3.10)
project(MyApp)
message("源码根目录: ${CMAKE_SOURCE_DIR}")
message("构建根目录: ${CMAKE_BINARY_DIR}")
message("当前源码目录: ${CMAKE_CURRENT_SOURCE_DIR}")
message("项目源码目录: ${PROJECT_SOURCE_DIR}")
# 添加子目录
add_subdirectory(${CMAKE_SOURCE_DIR}/src)
# 包含头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)
# 添加当前目录的源文件
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES)
- 平台特定目录变量
Windows 目录变量
cmake
Windows 特定路径
CMAKE_WINDOWS_DIR # Windows 目录
CMAKE_SYSTEM_DIR # 系统目录
CMAKE_PROGRAMFILES_DIR # Program Files 目录
Unix/Linux 目录变量
cmake
Unix/Linux 标准路径
CMAKE_ROOT # CMake 安装根目录
CMAKE_INSTALL_FULL_<DIR> # 完整安装路径
使用示例
cmake
# 平台特定的安装配置
if(WIN32)
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_LIBDIR "lib")
set(CMAKE_INSTALL_DATADIR "share")
elseif(UNIX)
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_LIBDIR "lib")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
set(CMAKE_INSTALL_LIBDIR "lib64")
endif()
endif()
- 模块和包目录变量
模块搜索路径
cmake
CMAKE_MODULE_PATH # CMake 模块搜索路径
CMAKE_PREFIX_PATH # 包搜索路径
CMAKE_FIND_ROOT_PATH # 交叉编译时的根路径
使用示例
cmake
# 添加自定义模块路径
list(APPEND CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake
${CMAKE_SOURCE_DIR}/cmake/modules
)
# 添加包搜索路径
list(APPEND CMAKE_PREFIX_PATH
/opt/local
/usr/local
${CMAKE_SOURCE_DIR}/third_party
)
# 查找包
find_package(OpenSSL REQUIRED)
find_package(Boost COMPONENTS filesystem system)
- 编译器相关目录变量
编译器路径
cmake
CMAKE_C_COMPILER # C 编译器路径
CMAKE_CXX_COMPILER # C++ 编译器路径
CMAKE_COMPILER_IS_GNUCC # 是否是 GNU C 编译器
CMAKE_COMPILER_IS_GNUCXX # 是否是 GNU C++ 编译器
使用示例
cmake
# 检查编译器
message("C 编译器: ${CMAKE_C_COMPILER}")
message("C++ 编译器: ${CMAKE_CXX_COMPILER}")
# 编译器特定设置
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
endif()
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()
- 完整项目示例
项目目录结构
text
myproject/
├── CMakeLists.txt
├── cmake/
│ └── FindMyLib.cmake
├── src/
│ ├── CMakeLists.txt
│ └── main.cpp
├── include/
│ └── myproject/
│ └── header.h
├── third_party/
│ └── somelib/
└── tests/
└── CMakeLists.txt
顶层 CMakeLists.txt
cmake
cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0.0 LANGUAGES C CXX)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 目录变量输出
message(STATUS "项目信息:")
message(STATUS " 项目名称: ${PROJECT_NAME}")
message(STATUS " 项目版本: ${PROJECT_VERSION}")
message(STATUS " 源码目录: ${CMAKE_SOURCE_DIR}")
message(STATUS " 构建目录: ${CMAKE_BINARY_DIR}")
message(STATUS " 当前目录: ${CMAKE_CURRENT_SOURCE_DIR}")
# 添加模块搜索路径
list(APPEND CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake
${CMAKE_CURRENT_SOURCE_DIR}/cmake
)
# 添加包搜索路径
list(APPEND CMAKE_PREFIX_PATH
${CMAKE_SOURCE_DIR}/third_party
)
# 安装目录配置
include(GNUInstallDirs)
# 自定义安装目录
set(MYPROJECT_INCLUDE_INSTALL_DIR
${CMAKE_INSTALL_INCLUDEDIR}/myproject
)
set(MYPROJECT_CMAKE_INSTALL_DIR
${CMAKE_INSTALL_LIBDIR}/cmake/myproject
)
# 添加子目录
add_subdirectory(src)
add_subdirectory(tests)
# 安装配置
install(
DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
)
# 导出包配置
install(EXPORT MyProjectTargets
FILE MyProjectTargets.cmake
NAMESPACE MyProject::
DESTINATION ${MYPROJECT_CMAKE_INSTALL_DIR}
)
src/CMakeLists.txt
cmake
# 打印当前目录信息
message(STATUS "源码构建目录: ${CMAKE_CURRENT_BINARY_DIR}")
# 添加源文件
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
)
# 添加头文件目录
include_directories(
${CMAKE_SOURCE_DIR}/include
${CMAKE_CURRENT_BINARY_DIR} # 用于生成的头文件
)
# 创建可执行文件
add_executable(myapp ${SOURCES})
# 设置输出目录
set_target_properties(myapp PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)
# 安装目标
install(TARGETS myapp
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
- 高级目录管理
自定义目录变量
cmake
# 定义项目特定的目录变量
set(MYPROJECT_SRC_DIR ${CMAKE_SOURCE_DIR}/src)
set(MYPROJECT_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
set(MYPROJECT_TEST_DIR ${CMAKE_SOURCE_DIR}/tests)
set(MYPROJECT_BUILD_DIR ${CMAKE_BINARY_DIR})
set(MYPROJECT_OUTPUT_DIR ${CMAKE_BINARY_DIR}/output)
# 创建自定义目录
file(MAKE_DIRECTORY ${MYPROJECT_OUTPUT_DIR}/bin)
file(MAKE_DIRECTORY ${MYPROJECT_OUTPUT_DIR}/lib)
file(MAKE_DIRECTORY ${MYPROJECT_OUTPUT_DIR}/include)
# 设置输出目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MYPROJECT_OUTPUT_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MYPROJECT_OUTPUT_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MYPROJECT_OUTPUT_DIR}/bin)
路径操作函数
cmake
# 获取相对路径
get_filename_component(RELATIVE_PATH
${CMAKE_CURRENT_SOURCE_DIR}
RELATIVE ${CMAKE_SOURCE_DIR}
)
# 获取绝对路径
get_filename_component(ABSOLUTE_PATH
"include/myheader.h"
ABSOLUTE
BASE_DIR ${CMAKE_SOURCE_DIR}
)
# 路径拼接
set(FULL_INCLUDE_PATH
${CMAKE_SOURCE_DIR}/include
)
# 检查路径是否存在
if(EXISTS ${FULL_INCLUDE_PATH})
message(STATUS "包含目录存在: ${FULL_INCLUDE_PATH}")
else()
message(WARNING "包含目录不存在: ${FULL_INCLUDE_PATH}")
endif()
- 交叉编译目录设置
交叉编译配置
cmake
# 设置交叉编译工具链
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 工具链路径
set(TOOLCHAIN_DIR /opt/arm-toolchain)
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/arm-linux-gnueabihf-g++)
# 系统根目录
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR}/arm-linux-gnueabihf)
# 只在目标系统中查找库
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
- 实用调试技巧
调试目录变量
cmake
# 打印所有目录变量
function(print_directory_variables)
message(STATUS "=== 目录变量 ===")
message(STATUS "CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_BINARY_DIR: ${CMAKE_BINARY_DIR}")
message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}")
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}")
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
endfunction()
# 在需要的地方调用
print_directory_variables()