install() 命令必须显式编写才生效,不自动推导;需用 install(targets ...) 指定构建产物并设 destination(如 bin),或 install(files/directory ...) 安装静态资源,路径一律为相对于 cmake_install_prefix 的相对路径。

install() 命令怎么写才生效?
CMake 的安装规则必须显式调用 install(),否则 make install 或 cmake --install 什么都不会复制。它不自动推导,也不依赖 target 是否被构建——哪怕 target 已存在,没写 install() 就没安装行为。
-
install(TARGETS ...)用于安装可执行文件、库等构建产物,必须指定DESTINATION(如bin、lib),否则报错 -
install(FILES ... DESTINATION ...)用于安装源码树里的静态文件(如配置模板、图标) -
install(DIRECTORY ... DESTINATION ...)适合安装整个资源目录,注意末尾斜杠影响是否复制目录本身 - 所有路径都是相对于
CMAKE_INSTALL_PREFIX(默认/usr/local),不是绝对路径
示例:安装一个叫 myapp 的可执行文件到 bin/,同时把 data/ 下所有文件装到 share/myapp/
install(TARGETS myapp DESTINATION bin) install(DIRECTORY data/ DESTINATION share/myapp)
DESTINATION 路径写相对还是绝对?
一律写相对路径。CMake 会自动拼到 CMAKE_INSTALL_PREFIX 后面。写成 /usr/bin 或 /opt/myapp/bin 看似直观,但会导致跨前缀失效(比如用 -DCMAKE_INSTALL_PREFIX=/tmp/staging 测试时仍硬编码到 /usr)。
- 常见合法值:
bin、lib、include、share/myapp、etc - 避免使用
../或以/开头的路径,CMake 会直接报错 - 如果真要覆盖系统级路径(如
/etc),应通过变量控制:install(... DESTINATION ${ETC_INSTALL_DIR}),再由用户传参定义ETC_INSTALL_DIR
怎么让 install() 只在特定构建类型下生效?
install() 本身没有条件开关,但它支持 EXCLUDE_FROM_ALL 和 OPTIONAL,更常用的是靠构建逻辑隔离:
使用
if(CMAKE_BUILD_TYPE STREQUAL "Release")包裹install()是错的——CMAKE_BUILD_TYPE在多配置生成器(如 Visual Studio、Xcode)下为空,不可靠-
正确做法是用
if(INSTALL_MYAPP)这类自定义 option 控制:option(INSTALL_MYAPP "Install myapp binaries and assets" ON) if(INSTALL_MYAPP) install(TARGETS myapp DESTINATION bin) endif()
然后构建时加-DINSTALL_MYAPP=OFF即可跳过 另一种场景:只在打包时安装(如 CPack),可用
if(CPACK_PACKAGE_NAME),但注意 CPack 变量仅在 CPack 配置阶段可见
install(FILES ...) 为什么文件没被复制?
最常见原因是源路径写错了。CMake 的 FILES 参数要求路径在 configure 阶段就存在,且是相对于当前 CMakeLists.txt 所在目录的路径。
- 错误写法:
install(FILES /abs/path/to/logo.png DESTINATION share/icons)—— 绝对路径会被拒绝 - 错误写法:
install(FILES logo.png DESTINATION share/icons),但当前目录下根本没有logo.png—— CMake 不报错,但 install 时静默跳过 - 正确写法:确保文件存在,或用
file(GLOB ...)收集后再传给install(FILES ...),但注意 GLOB 不自动 reconfigure,推荐用显式列表
另外,install(FILES ...) 默认不设权限,Linux 下可能丢失可执行位。需要时加 PERMISSIONS OWNER_EXECUTE 等参数。
CMake 安装规则的核心就两条:路径必须相对、install() 必须显式写。容易被忽略的是 DESTINATION 的拼接逻辑和源文件路径的上下文——它不看构建目录,只认 CMakeLists.txt 所在位置。











