cmake --install 不编译也不生成构建系统,仅执行 configure 阶段登记的 install() 规则,将已构建产物(如 libxxx.so、xxx.h)按 DESTINATION 路径复制到 CMAKE_INSTALL_PREFIX 下;前提是必须先运行 cmake --build 完成编译,否则因文件缺失而报错。

cmake --install 是怎么把文件拷到指定目录的
它不自己编译,也不生成构建系统,只是执行 CMakeLists.txt 里 install() 命令定义好的规则,把已构建好的目标(如 libxxx.so、xxx.h)按路径复制过去。关键前提是:你得先用 cmake --build 把东西编译出来,否则 cmake --install 会报错找不到目标。
常见错误现象:
-
CMake Error: install TARGETS given no LIBRARY DESTINATION for shared library——install(TARGETS ...)没写LIBRARY DESTINATION或其他对应类型(RUNTIME/ARCHIVE) -
file INSTALL cannot find—— 头文件路径写错,或install(FILES ...)指向了未生成/不存在的文件
install() 命令怎么写头文件和库的安装规则
头文件和库必须分开声明,不能混在同一个 install() 里。库用 TARGETS,头文件用 FILES 或 DIRECTORY。
- 安装动态库和静态库:
install(TARGETS mylib RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) - 安装单个头文件:
install(FILES include/mylib.h DESTINATION include) - 安装整个头文件目录(保留子目录结构):
install(DIRECTORY include/ DESTINATION include) - 如果头文件分散在多个源目录,且项目没提供
include/目录,得手动install(FILES ...)列出或用install(DIRECTORY ...)指定源路径
注意:DESTINATION 是相对于 CMAKE_INSTALL_PREFIX 的路径,不是绝对路径。比如 -DCMAKE_INSTALL_PREFIX=/opt/mylib + DESTINATION include → 最终路径是 /opt/mylib/include。
CMake 4.3.2 Windows x86_64 历史版本安装包,适合旧项目兼容、构建环境回退、CMakeLists.txt 迁移验证、Visual Studio/Ninja/Makefile 生成器测试和 C/C++ 项目维护。
CMAKE_INSTALL_PREFIX 必须提前设置好
这个变量决定了所有 install() 规则的根目录,必须在配置阶段(cmake .. -DCMAKE_INSTALL_PREFIX=...)就传入,运行 cmake --install 时不能再改。
- Windows 下路径分隔符建议用正斜杠
/或双反斜杠\,避免单反斜杠被转义 - 路径末尾不要加斜杠,
-DCMAKE_INSTALL_PREFIX=D:/work/install/和-DCMAKE_INSTALL_PREFIX=D:/work/install效果一样,但后者更稳妥 - 该路径所在磁盘/目录必须有写权限;若指向
/usr/local等系统目录,需 sudo 权限(Linux/macOS)或管理员权限(Windows)
为什么 cmake --install --config Release 在 Windows 上容易失败
因为 MSVC 生成器是多配置的(Debug/Release),--config 必须和之前 cmake --build 用的配置严格一致,否则找不到对应构建产物。
- 如果
cmake --build . --config Debug了,却运行cmake --install . --config Release,会提示找不到mylib.lib或mylib.dll - Unix Makefiles/Ninja 这类单配置生成器不支持
--config,直接去掉该参数,否则报错 - 检查是否真有对应配置的输出:看
build/目录下是否存在Debug/或Release/子目录,以及里面是否有.lib/.dll文件
最易被忽略的一点:install 规则本身不会自动推导头文件依赖关系——如果你改了头文件但没重新运行 cmake --build,cmake --install 仍会拷旧版本;它只管“拷”,不管“新不新”。

















