
CMake 044 install 奥义详解 · 骈文篇◇◆◇ 【卷首语】编译之终部署之始 ◇◆◇Bilibili 同步视频◆◇◆ 【第一章】install 之功用 · 双剑合璧 ◆◇◆✦ 第一节 · 文件部署之能 ✦「分门别类各归其位」✦ 第二节 · find_package 之基 ✦「一劳永逸万物可寻」◇◆◇ 【第二章】代码准备之章 · 三器齐铸 ◇◆◇✦ 第一节 · 静态库之铸 ✦「s_lib · 静而内藏」✦ 第二节 · 动态库之炼 ✦「d_lib · 动而外显」✦ 第三节 · 执行程序之合 ✦「main · 主而统之」◆◇◆ 【第三章】install target 之法 · 初窥门径 ◆◇◆✦ 第一节 · 基本语法 ✦「一言以蔽之一令以统之」✦ 第二节 · CMAKE_INSTALL_PREFIX ✦「前缀之妙路径之根」◇◆◇ 【第四章】跨平台之辨 · 殊途同归 ◇◆◇✦ 第一节 · Linux 之境 ✦「usr/local权限为要」✦ 第二节 · Windows 之域 ✦「Debug Release版本为纲」◆◇◆ 【第五章】易错陷阱之鉴 · 前车之覆 ◆◇◆❌ 陷阱一Windows 动态库导出失败「cpp 不包含头文件导出宏徒然」❌ 陷阱二Windows 版本不匹配「编译 Debug安装 Release南辕北辙」❌ 陷阱三Linux 权限不足「欲装系统目录却无 root 权限」❌ 陷阱四头文件未设 PUBLIC「依赖者找不到头文件编译报错」❌ 陷阱五INSTALL_PREFIX 写死「路径写死在代码僵化不灵」◇◆◇ 【第六章】进阶展望 · 后事分解 ◇◆◇◆◇◆ 【卷末语】技进乎道融会贯通 ◆◇◆✦ 延伸阅读 ✦✨ 博客特色概览 骈文风格 符号装饰 技术深度◇◆◇ 【卷首语】编译之终部署之始 ◇◆◇═══════════════════════════════════════盖闻编程之道编译为本部署为要代码千行止于编译若无安装犹明珠暗投宝剑蒙尘。昔者开源之世make install一令既出头文件归其位库文件入其所执行程序赴其途开发者但引其头、链其库便可运筹帷幄决胜千里。然 CMake 之中install指令之妙岂止拷贝文件之能更有find_package之基使模块可寻库可复用实乃工程化之津梁也。今作此篇以骈文之体述 install 之术愿读者诸君得其精要融会贯通于跨平台开发之途如虎添翼事半功倍═══════════════════════════════════════Bilibili 同步视频CMake 044 install 奥义详解 · 骈文篇◆◇◆ 【第一章】install 之功用 · 双剑合璧 ◆◇◆═══════════════════════════════════════✦ 第一节 · 文件部署之能 ✦「分门别类各归其位」───────────────────────────────────────夫编译者止生成本机之产物安装者方为发布之始也。编译之所出二进制文件、静态库、动态库皆散于构建目录之中杂然无序。安装之所能不独编译之产物更兼资源之文件头文件、配置项、文档册凡所有者皆可安装至指定之位。━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━何以必须 install 耶盖因机器各异路径不同编译之时岂能预设万端唯有安装之际指定路径方能统一部署各得其所。譬若开源之项目make install一令既下头文件入/usr/include库文件归/usr/lib执行程序赴/usr/bin井然有序丝毫不乱。开发者但需包含头、链接库便可直接使用无需繁琐配置此 install 之第一大功也───────────────────────────────────────✦ 第二节 · find_package 之基 ✦「一劳永逸万物可寻」───────────────────────────────────────CMake 之妙尤在find_package一令既出万库可寻无需手动指定路径无需繁琐配置项。然find_package何以能寻实赖 install 之功也盖因安装之时CMake 不仅拷贝文件更生成配置之文件记录库之所在、头之路径、编译之选项。于是乎大型项目之中模块众多但经 install 部署便可find_package一键导入如探囊取物易如反掌。此 install 之第二大功也═══════════════════════════════════════◇◆◇ 【第二章】代码准备之章 · 三器齐铸 ◇◆◇═══════════════════════════════════════古语有云工欲善其事必先利其器。欲探 install 之奥必先备测试之码。今铸三器以试牛刀一曰静态之库s_lib静而内藏二曰动态之库d_lib动而外显三曰执行之程序main主而统之。三者齐备方可演示 install 之种种妙用。───────────────────────────────────────✦ 第一节 · 静态库之铸 ✦「s_lib · 静而内藏」───────────────────────────────────────静态库者编译之时融入程序执行之日无需外挂其形如.aLinux或.libWindows静若处子内藏玄机。目录之结构s_lib/ ├── include/ │ └── s_lib.h ← 公有头文件向外暴露 ├── s_lib.cpp ← 实现文件 └── s_lib_private.h ← 私有头文件内部使用公有头文件 ****s_lib.h#ifndef S_LIB_H #define S_LIB_H void s_library(); // 公开接口供外部调用 #endif // S_LIB_H私有头文件 ****s_lib_private.h// 私有头文件仅供内部使用不对外安装 // 此处可放置内部实现细节、辅助函数等实现文件 ****s_lib.cpp#include s_lib.h #include s_lib_private.h // 简单实现仅用于演示编译安装流程 void s_library() { // 实际项目中此处为具体业务逻辑 }CMake 之配置# 添加静态库目标 add_library(s_library STATIC s_lib.cpp include/s_lib.h s_lib_private.h ) # 指定公有头文件目录使依赖者可自动找到头文件 target_include_directories(s_library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include )要点提示PUBLIC关键字至关重要不仅本目标可用依赖此库者亦自动继承省却手动指定头文件路径之烦。───────────────────────────────────────✦ 第二节 · 动态库之炼 ✦「d_lib · 动而外显」───────────────────────────────────────动态库者运行之时加载入内存多程序共享节省空间其形如.soLinux、.dllWindows、.dylibMac动若脱兔外显其能。然 Windows 之下动态库尤难若无导出之宏则符号不外露虽编译成功却无.lib导入库他者欲链接之势比登天。故 Windows 动态库必加导出之宏头文件 ****d_lib.h#ifndef D_LIB_H #define D_LIB_H // Windows 平台专属导出宏定义 #ifdef _WIN32 #ifdef D_LIB_EXPORTS #define D_LIB_API __declspec(dllexport) #else #define D_LIB_API __declspec(dllimport) #endif #else // Linux/Mac 无需导出宏默认全部可见 #define D_LIB_API #endif // 导出函数声明 D_LIB_API void d_library(); #endif // D_LIB_H实现文件 ****d_lib.cpp// ⚠️ 关键必须包含头文件 // 若 cpp 不包含 h则导出宏不参与编译 // Windows 下将无法生成 .lib 导入库 #include d_lib.h // 简单实现 void d_library() { // 实际项目中此处为具体业务逻辑 }⚠️重中之重.cpp文件务必包含对应头文件否则导出宏代码不参与编译Windows 下动态库导出失败无.lib文件生成他者无法链接。CMake 之配置# 添加动态库目标 add_library(d_library SHARED d_lib.cpp include/d_lib.h ) # 指定公有头文件目录 target_include_directories(d_library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) # Windows 下定义导出宏 if(WIN32) target_compile_definitions(d_library PRIVATE D_LIB_EXPORTS) endif()各平台动态库产物一览平台动态库文件导入库文件说明Linuxlibd_library.so——无需导入库Windowsd_library.dlld_library.lib.lib为导入库非静态库MacOSlibd_library.dylib——与 Linux 类似───────────────────────────────────────✦ 第三节 · 执行程序之合 ✦「main · 主而统之」───────────────────────────────────────既铸二库当合而为一执行程序链接二者以验编译之效以测安装之能。主程序 ****main.cpp// 引用静态库头文件 #include s_lib.h // 引用动态库头文件 #include d_lib.h int main() { // 调用静态库函数 s_library(); // 调用动态库函数 d_library(); return 0; }CMake 之配置# 添加可执行程序目标 add_executable(${PROJECT_NAME} main.cpp) # 链接静态库与动态库 target_link_libraries(${PROJECT_NAME} PRIVATE s_library d_library )编译验证之法Linux 平台cmake -S . -B build cmake --build build编译既成观其链接可执行程序链接d_lib.so动态库静态库s_lib.a则融入其中运行之时唯需动态库相伴。Windows 平台cmake -S . -B build cmake --build build编译既成察其产物d_library.dll动态库、d_library.lib导入库、s_library.lib静态库、可执行程序四者俱全方为成功。═══════════════════════════════════════◆◇◆ 【第三章】install target 之法 · 初窥门径 ◆◇◆═══════════════════════════════════════✦ 第一节 · 基本语法 ✦「一言以蔽之一令以统之」───────────────────────────────────────CMake 安装目标之指令名曰install其形简约其用无穷。基础之语法install(TARGETS 目标1 目标2 目标3 ... DESTINATION 安装路径)示例之代码# 将静态库、动态库、可执行程序全部安装至 bin 目录 install(TARGETS s_library # 静态库 d_library # 动态库 ${PROJECT_NAME} # 可执行程序 DESTINATION bin )关键字解析TARGETS指定要安装的目标库、可执行程序等DESTINATION指定安装的目标路径相对路径───────────────────────────────────────✦ 第二节 · CMAKE_INSTALL_PREFIX ✦「前缀之妙路径之根」───────────────────────────────────────DESTINATION之后虽为路径然非绝对乃相对也。相对者何相对CMAKE_INSTALL_PREFIX也。此变量者安装之根目录也犹如大树之根万枝由此而生。━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━指定之法法一命令行传入推荐cmake -S . -B build -DCMAKE_INSTALL_PREFIX./out为何推荐命令行盖因不同机器路径各异写死在 CMakeLists.txt 中僵化不灵命令行传入灵活多变因地制宜。法二CMakeLists.txt 中设置不推荐set(CMAKE_INSTALL_PREFIX ./out CACHE PATH Install path prefix)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━完整安装之流程# 第一步配置项目指定安装前缀 cmake -S . -B build -DCMAKE_INSTALL_PREFIX./out # 第二步编译项目 cmake --build build # 第三步执行安装 cmake --install build执行既毕可往./out/bin目录观之静态库、动态库、可执行程序三者俱全井然有序。═══════════════════════════════════════◇◆◇ 【第四章】跨平台之辨 · 殊途同归 ◇◆◇═══════════════════════════════════════天下平台三分天下Linux、Windows、MacOS各有规矩各有习俗。CMake 虽曰跨平台然细节之处仍需明辨。───────────────────────────────────────✦ 第一节 · Linux 之境 ✦「usr/local权限为要」───────────────────────────────────────Linux 之下默认安装路径为何答曰/usr/local是也。若不指定CMAKE_INSTALL_PREFIX则头文件入/usr/local/include库文件归/usr/local/lib执行程序赴/usr/local/bin。━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━权限之问题然/usr/local者系统之目录也普通用户无写入之权。若强行安装必报权限之错。解法有二法一sudo 提权sudo cmake --install build法二自定义路径推荐开发时使用cmake -S . -B build -DCMAKE_INSTALL_PREFIX./out cmake --install build开发建议日常开发调试宜安装至当前目录既免权限之烦又不污染系统干净利落进退自如。───────────────────────────────────────✦ 第二节 · Windows 之域 ✦「Debug Release版本为纲」───────────────────────────────────────Windows 之下情形尤异Debug 与 Release泾渭分明产物分处不同目录不可混为一谈。━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━版本之陷阱⚠️天坑预警CMake 默认编译 Debug 版本然默认安装 Release 版本二者不一致必致安装失败此乃初学者最易踩之坑编译成功安装报错百思不得其解实则版本不匹配也。━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━解法之法法一安装时指定版本# 安装 Debug 版本 cmake --install build --config Debug # 安装 Release 版本 cmake --install build --config Release法二编译时即指定 Release 版本# 编译 Release 版本 cmake --build build --config Release # 安装默认即 Release无需额外参数 cmake --install build━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━完整 Windows 流程# 配置项目指定安装路径 cmake -S . -B build -DCMAKE_INSTALL_PREFIX./win_out # 编译 Debug 版本 cmake --build build --config Debug # 安装 Debug 版本 cmake --install build --config DebugWindows 小贴士若安装至系统目录如C:Program Files需以管理员身份运行终端否则权限不足安装失败。═══════════════════════════════════════◆◇◆ 【第五章】易错陷阱之鉴 · 前车之覆 ◆◇◆═══════════════════════════════════════古语有云前车之覆后车之鉴。今录常见陷阱若干愿读者诸君避而远之少走弯路直达彼岸。───────────────────────────────────────❌ 陷阱一Windows 动态库导出失败「cpp 不包含头文件导出宏徒然」症状Windows 下编译动态库只生成.dll不生成.lib其他项目无法链接。病因.cpp文件未包含对应头文件导出宏代码不参与编译符号未导出自然无导入库。药方确保每个.cpp都包含对应头文件导出宏方能生效.lib自然生成。───────────────────────────────────────❌ 陷阱二Windows 版本不匹配「编译 Debug安装 Release南辕北辙」症状编译成功安装报错提示找不到目标文件。病因默认编译 Debug产物在 Debug 目录默认安装 Release去 Release 目录寻找自然空空如也。药方安装时务必指定--config Debug或编译时即指定--config Release二者版本一致方能成功。───────────────────────────────────────❌ 陷阱三Linux 权限不足「欲装系统目录却无 root 权限」症状安装时报错提示 Permission denied。病因默认安装路径/usr/local普通用户无写入权限。药方开发时自定义安装路径或使用sudo提权安装。───────────────────────────────────────❌ 陷阱四头文件未设 PUBLIC「依赖者找不到头文件编译报错」症状可执行程序编译时提示找不到库的头文件。病因库的头文件目录未设为PUBLIC依赖者无法自动继承。药方使用target_include_directories时务必加上PUBLIC关键字使依赖者自动获得头文件路径。───────────────────────────────────────❌ 陷阱五INSTALL_PREFIX 写死「路径写死在代码僵化不灵」症状换台机器就报错路径不对。病因在 CMakeLists.txt 中写死安装路径不同机器目录结构不同自然出错。药方通过命令行-DCMAKE_INSTALL_PREFIX...传入灵活多变因地制宜。═══════════════════════════════════════◇◆◇ 【第六章】进阶展望 · 后事分解 ◇◆◇═══════════════════════════════════════本篇所述乃 install 之基础也三器同装于一目录仅为入门之法。然实际项目之中岂能如此简陋头文件当归include库文件应入lib执行程序需赴bin文档册宜往share/doc各归其位井然有序。更有安装文件——单独安装头文件、配置文件安装目录——批量安装整个目录可排除特定文件权限设置——Linux 下指定文件权限版本配置——Debug/Release 分别安装至不同目录组件安装——按组件分类安装按需选择凡此种种皆 install 之妙用也且听下回分解。═══════════════════════════════════════◆◇◆ 【卷末语】技进乎道融会贯通 ◆◇◆═══════════════════════════════════════嗟夫CMake install 之术看似简单实则蕴含工程化之大道。编译者代码之终也安装者发布之始也。由编译而安装由开发而部署此乃软件生命周期之正道也。愿读者诸君不仅知其然更知其所以然于跨平台开发之途游刃有余得心应手。若本篇对君有所裨益还望点赞、收藏、关注三连不胜感激之至═══════════════════════════════════════✦ 延伸阅读 ✦相关文章推荐《CMake 入门到精通 · 基础篇》《CMake target_include_directories 详解》《跨平台动态库开发最佳实践》《find_package 原理与自定义配置文件》官方文档CMake install 命令官方文档CMAKE_INSTALL_PREFIX 变量说明═══════════════════════════════════════✦ 全文完 · 感谢阅读 ✦═══════════════════════════════════════技术博客已撰写完成以下是本篇博客的核心亮点✨ 博客特色概览 骈文风格全文采用骈文对仗笔法如「编译之终部署之始」「分门别类各归其位」「一劳永逸万物可寻」「静若处子内藏玄机动若脱兔外显其能」读来朗朗上口技术文章亦有文学之美。 符号装饰大量使用装饰符号提升视觉层次分隔线══════──────━━━━━━章节标记◇◆◇◆◇◆重点符号✦⚠️❌表格、代码块、引用块丰富排版 技术深度涵盖5 大核心模块install 两大功用——文件部署 find_package 基础三类目标代码——静态库、动态库、可执行程序完整示例install target 基础语法——含完整命令流程跨平台详解——Linux 权限问题 Windows 版本陷阱五大易错陷阱——每个陷阱附症状、病因、药方你可以直接复制到 CSDN 发布如需调整某个章节的风格或补充更多技术细节随时告诉我