cmake_install_prefix 是唯一需关注的安装路径变量,其他路径均由其派生;可通过命令行 -dcmake_install_prefix 设置、cmake --install --prefix 覆盖安装时路径,或在 cmakelists.txt 中用 if(cmake_install_prefix_initialized_to_default) 设默认值。

CMAKE_INSTALL_PREFIX 是唯一需要关心的变量,其他路径都由它派生
cmake 命令行设置 -DCMAKE_INSTALL_PREFIX 最常用
这是最直接、最可控的方式,适合 CI/CD、临时测试或不同环境部署。执行时覆盖所有默认和 CMakeLists.txt 中的设置:
- Linux/macOS:
cmake .. -DCMAKE_INSTALL_PREFIX=/opt/myapp - Windows(PowerShell):
cmake .. -DCMAKE_INSTALL_PREFIX="C:/Program Files/myapp" - 注意:路径中不要加引号包裹斜杠分隔符;Windows 用正斜杠
/更安全,CMake 内部会自动转换 - 如果路径含空格(如
C:/Program Files),必须加双引号,否则 cmake 解析失败,报错Parse error in command line argument
cmake --install --prefix 覆盖安装时路径(CMake 3.15+)
这个参数只在安装阶段生效,不影响构建过程,且优先级高于 CMakeLists.txt 和命令行 -D 设置,适合打包脚本或灰度发布:
- 先构建:
cmake --build build - 再安装到指定位置:
cmake --install build --prefix /tmp/staging - 常见错误:漏掉
build目录名,写成cmake --install . --prefix ...会报Cannot determine source directory - 搭配
DESTDIR可做“零污染”测试:cmake --install build --prefix /usr --DESTDIR /tmp/fakeroot,最终文件落在/tmp/fakeroot/usr/bin/
CMakeLists.txt 中设默认值 - 仅当未被外部覆盖时生效
适用于想让新手开箱即用,又不破坏高级用户的自定义流程。关键点是判断是否为初始默认值:
- 正确写法:
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "Install path" FORCE) endif() - 错误写法:
set(CMAKE_INSTALL_PREFIX "/opt/myapp")—— 这会强制覆盖,用户传-DCMAKE_INSTALL_PREFIX=...也无效 - 注意:
CACHE STRING必须带FORCE,否则第一次 configure 后该变量就“固化”了,后续改 CMakeLists.txt 也不生效 - Windows 用户需留意:默认值是
c:/Program Files/${PROJECT_NAME},但若系统无写入权限,make install会静默失败或提示Permission denied
install() 命令里的 DESTINATION 是相对路径,不是绝对路径
install(TARGETS mylib LIBRARY DESTINATION lib) 中的 lib 不是系统 /usr/lib,而是拼在 CMAKE_INSTALL_PREFIX 后面的子目录:
- 若
CMAKE_INSTALL_PREFIX=/opt/myapp,则实际安装到/opt/myapp/lib/ - 不能写成
DESTINATION /lib(开头斜杠)—— 这会被当作绝对路径,绕过前缀,导致混装风险 - 跨平台陷阱:Windows 下
DESTINATION bin生成myapp\bin\,但若项目里硬编码../bin/tool.exe,在非默认 prefix 下会找错位置 - 调试技巧:运行
cmake --build build --target help查看installtarget 是否存在;用cmake -LH build检查CMAKE_INSTALL_PREFIX当前值
真正容易被忽略的是:CMAKE_INSTALL_PREFIX 的值一旦在 configure 阶段确定,后续所有 install() 行为都不可逆地绑定它;哪怕你在 install 前用 set() 修改变量,也不会影响已解析的 DESTINATION 路径。











