--- name: third-party-libs description: 第三方编译库管理规范。用于新增、修改或引用 third_party 下需编译的第三方库时,统一目录结构、架构分层与 CMake 链接方式。 --- # 第三方编译库管理规范 ## 适用范围 `third_party/` 目录下所有**需要编译**的 C/C++ 第三方库。 纯头文件库(如 `nlohmann`、`spdlog`)不受此规范约束。 ## 编译架构原则 - 默认只编译、整理**当前运行机器架构**的库或工具文件。 - 禁止在未被明确要求时自动交叉编译其他架构产物。 - 需要 arm64/x64 等非当前架构产物时,必须由用户明确要求或提供已编译产物,再按对应架构目录放置。 - 同一次任务中不要为了“完整性”主动补齐所有架构;以当前部署目标为准。 ## 目录结构 每个需要编译的第三方库拆分为两个目录: ``` third_party/ ├── <库名>/ # 编译产物(头文件 + 静态/动态库) │ ├── include/ # 公开头文件 │ └── libs/ # 编译后的库文件,按架构分层 │ ├── x64/ │ ├── arm32/ │ └── arm64/ └── <库名>_repo/ # 源码仓库(带 _repo 后缀标识) ``` ### 示例 ``` third_party/ ├── fwlib/ # Fanuc SDK 编译产物 │ ├── include/ │ └── libs/{x64,arm32,arm64}/ ├── fwlib_repo/ # Fanuc SDK 源码 ├── lib60870/ # IEC 60870 编译产物 │ ├── include/ │ └── libs/{x64,arm32,arm64}/ ├── lib60870_repo/ # IEC 60870 源码 ├── libplctag/ # CIP/EtherNet/IP 编译产物 │ ├── include/ │ └── libs/{x64,...}/ ├── paho-mqtt/ # MQTT 编译产物 │ ├── include/ │ └── libs/{x64,...}/ ├── nlohmann/ # 纯头文件库(不受此规范约束) └── spdlog/ # 纯头文件库(不受此规范约束) ``` ## 命名规则 | 目录 | 用途 | 示例 | |------|------|------| | `<库名>/` | 编译产物(include + libs) | `fwlib/`、`libplctag/` | | `<库名>_repo/` | 源码仓库,用 `_repo` 后缀区分 | `fwlib_repo/`、`lib60870_repo/` | ## 架构标识 库文件必须放在 `libs//` 子目录下,`` 取值: | 架构标识 | 对应处理器 | |----------|-----------| | `x64` | x86_64 | | `arm32` | armv7l / arm | | `arm64` | aarch64 / arm64 | ## CMake 链接规范 ### 架构检测(统一写法) ```cmake if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv7.*|arm)$") set(TARGET_ARCH "arm32") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$") set(TARGET_ARCH "arm64") else() set(TARGET_ARCH "x64") endif() ``` ### 引用编译产物 ```cmake set(XXX_DIR "${REPO_ROOT}/third_party/<库名>") # 头文件 target_include_directories(target PRIVATE ${XXX_DIR}/include) # 链接库(使用 TARGET_ARCH 定位架构) target_link_libraries(target ${XXX_DIR}/libs/${TARGET_ARCH}/libxxx.a) # 或通过 link_directories target_link_directories(target PRIVATE ${XXX_DIR}/libs/${TARGET_ARCH}) target_link_libraries(target xxx) ``` ### 条件编译(可选库) 对于非必须的协议库,使用 `EXISTS` 检测并控制编译: ```cmake set(XXX_DIR "${REPO_ROOT}/third_party/<库名>") if(EXISTS "${XXX_DIR}/libs/${TARGET_ARCH}/libxxx.a") target_include_directories(target PRIVATE ${XXX_DIR}/include) target_link_libraries(target ${XXX_DIR}/libs/${TARGET_ARCH}/libxxx.a) target_compile_definitions(target PRIVATE HAS_XXX=1) message(STATUS "<库名> found — XXX driver enabled") else() get_target_property(_sources target SOURCES) list(FILTER _sources EXCLUDE REGEX ".*driver/xxx/.*") set_target_properties(target PROPERTIES SOURCES "${_sources}") message(STATUS "<库名> NOT found — XXX driver disabled") endif() ``` ## 禁止事项 - **禁止** 将编译后的库文件直接放在 `lib/` 而不分架构 - **禁止** 在 CMake 中硬编码 `lib/` 路径,必须使用 `libs/${TARGET_ARCH}/` - **禁止** 将源码和编译产物混放在同一目录 - **禁止** 将 `third_party` 改名为 `third_partys`(`third_party` 是业界标准命名) ## 新增第三方库流程 1. 将源码克隆到 `third_party/<库名>_repo/` 2. 编译出目标架构的库文件 3. 创建 `third_party/<库名>/include/`,放入公开头文件 4. 创建 `third_party/<库名>/libs//`,放入编译产物 5. 在 CMakeLists.txt 中按上述规范引用