1# SBOM 2 3## 简介 4 5本工具基于 **GN 构建元数据**,遵循 **OpenHarmony SBOM 中间态元数据格式**,生成标准化的中间实例,并输出符合 SPDX 2.3 规范的 SBOM 文件。 6 7无需依赖任何外部服务,满足OH社区**安全治理**、**开源合规治理**、**开源软件管理**述求。 8 9## 目录 10 11``` 12/sbom # SBOM工具根目录 13 14├── __pycache__ 15├── analysis/ # 依赖关系构建,包括依赖图、文件依赖关系和包依赖关系构建 16├── common/ # 工具类 17├── converters/ # 转换器,将SBOM元数据转换为各种标准的JSON格式 18├── data/ # `gn_gen`、`manifest`等元数据模型字段集中配置管理 19├── extraction/ # 负责加载构建系统生成的 `gn_gen.json`等关键资源并提取版权许可证信息 20├── pipeline/ # SBOM 生成核心流程控制器,将构建系统信息转化为标准化的SBOM 结构,是 SBOM 生成主入口 21├── sbom 22│ ├── builder/ # SBOM建造者,提供SBOM生成工具类 23│ └── config/ # SBOM 模型字段的集中配置与管理,提供基于 JSON 配置的字段元数据管理 24│ └── metadata/ # 定义 SBOM 元数据的核心数据模型,包括文档信息、软件包、文件、依赖关系等 25│ └── vaildation/ # SBOM字段级验证工具,支持通过声明式方式检查必填字段是否具有有效值 26├── generate_sbom.py* 27``` 28 29 30## 说明 31 32**代码根目录下执行全量版本的编译命令** 33 34~~~shell 35sbom生成默认为关闭 36 37使用如下命令: 38``` 39/build.sh --product-name {product_name} --sbom=true 40``` 41 42sbom输出在 out/{product_name}/sbom/目录下。 43~~~ 44 45**输出** 46 47``` 48out/{product_name}/sbom/ # sbom输出根目录 49 50├── sbom_meta_date.json # SBOM中间态 json 文件 51├── spdx.json # SPDX格式 SBOM 文件 52``` 53 541. **SBOM中间态文件** 55 56 包含以下四个字段 57 58 - document 59 60 本 SBOM 文档的元数据,包含标识、版本、时间戳、作者、工具等核心信息。 61 62 | 字段名 | 类型 | 是否必选 | 说明 | 63 | -------------------- | ------ | ------------------- | ------------------------ | 64 | `serialNumber` | 字符串 | 必选 | 文档的唯一标识符 | 65 | `docId` | 字符串 | SPDX 必选,其他可选 | 文档的唯一 ID | 66 | `name` | 字符串 | SPDX 必选,其他可选 | 文档所描述的软件名称 | 67 | `documentNamespace` | 字符串 | SPDX 必选,其他可选 | 文档的全局唯一命名空间 | 68 | `version` | 字符串 | 必选 | 文档的版本号 | 69 | `bomFormat` | 字符串 | 必选 | SBOM 的格式标识 | 70 | `specVersion` | 字符串 | 必选 | 所遵循规范的版本号 | 71 | `dataLicense` | 字符串 | 必选 | SBOM 数据的许可声明 | 72 | `licenseListVersion` | 字符串 | SPDX 必选,其他可选 | 许可证列表的版本号 | 73 | `timestamp` | 字符串 | 必选 | 文档生成的时间戳 | 74 | `authors` | 数组 | 必选 | 文档创建者的标识 | 75 | `lifecycles` | 数组 | 可选 | 覆盖的软件生命周期阶段 | 76 | `properties` | 数组 | 可选 | 用户自定义的附加属性 | 77 | `tools` | 数组 | 可选 | 生成文档所使用的工具信息 | 78 | `docComments` | 字符串 | 可选 | 对文档的整体说明或注释 | 79 80 - files 81 82 记录构成软件的各个文件的路径、校验和、许可证结论及版权声明等详细信息。 83 84 | 字段名 | 类型 | 是否必选 | 说明 | 85 | -------------------- | ------ | ------------------ | -------------------------- | 86 | `fileName` | 字符串 | 必选 | 文件名称或路径 | 87 | `fileAuthor` | 字符串 | 团标必选,其他可选 | 文件作者 | 88 | `fileId` | 字符串 | 必选 | 文件标识符 | 89 | `fileTypes` | 数组 | 可选 | 文件类型数组 | 90 | `checksums` | 数组 | 必选 | 文件的校验和信息 | 91 | `licenseConcluded` | 字符串 | 必选 | 许可证结论 | 92 | `licenseInfoInFiles` | 数组 | 可选 | 文件中声明的许可证信息数组 | 93 | `copyrightText` | 字符串 | 可选 | 版权声明 | 94 95 - packages 96 97 描述软件包的基本属性,包括名称、版本、供应商、许可证、唯一标识及哈希值等元数据。 98 99 | 字段名 | 类型 | 是否必选 | 说明 | 100 | ------------------ | ------ | ------------------------ | ------------------------------- | 101 | `type` | 字符串 | CycloneDX 必选,其他可选 | 组件类型 | 102 | `supplier` | 字符串 | 必选 | 供应商 | 103 | `group` | 字符串 | 必选 | 组件的组标识 | 104 | `name` | 字符串 | 必选 | 组件的名称 | 105 | `version` | 字符串 | 必选 | 组件的版本号 | 106 | `purl` | 字符串 | 必选 | 组件的唯一标识 | 107 | `licenseConcluded` | 字符串 | 必选 | 实际许可证 | 108 | `licenseDeclared` | 字符串 | 必选 | 作者声明的许可证 | 109 | `comCopyright` | 字符串 | 可选 | 版权声明 | 110 | `bom-ref` | 字符串 | 必选 | 文档内部唯一标识符,可复用 purl | 111 | `downloadLocation` | 字符串 | 可选 | 下载来源 | 112 | `hashes` | 数组 | 必选 | hash 值 | 113 | `compPlatform` | 字符串 | 团标必选,其他可选 | 组件平台架构 | 114 115 - relationships 116 117 定义组件与文件或其他组件之间的依赖或关联关系,明确软件结构与组成逻辑。 118 119 | 字段名 | 类型 | 是否必选 | 说明 | 120 | ------------------ | ------ | -------- | ---------------------------------------------------- | 121 | `bom-ref` | 字符串 | 必选 | 当前组件或服务的引用标识符 | 122 | `dependsOn` | 数组 | 必选 | 当前组件或服务所依赖的其他组件或服务的引用标识符列表 | 123 | `relationshipType` | 字符串 | 必选 | 依赖类型 | 124 1252. **SPDX文件** 126 127 目前输出SPDX2.3 格式,参考文档[SPDX Specification 2.3.0](https://spdx.github.io/spdx-spec/v2.3/) 128 129**输出示例** 130 1311. **镜像上文件** 132 133 ```json 134 # sbom 中间态格式 135 # 镜像上文件信息 136 # 以镜像上文件 system/app/com.ohos.adminprovisioning/adminprovisioning.hap 作为起点 137 { 138 "copyrightText": "NOASSERTION", 139 "fileAuthor": "NOASSERTION", 140 "fileId": "system/app/com.ohos.adminprovisioning/adminprovisioning.hap", 141 "fileName": "adminprovisioning.hap" 142 } 143 # 安装到镜像上文件依赖 144 # 此镜像上文件由 //out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap 拷贝产生 145 { 146 "bom-ref": "system/app/com.ohos.adminprovisioning/adminprovisioning.hap", 147 "dependsOn": [ 148 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap" 149 ], 150 "relationshipType": "COPY_OF" 151 } 152 # 构建生成文件 153 # 构建文件 //out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap 信息 154 { 155 "copyrightText": "NOASSERTION", 156 "fileAuthor": "NOASSERTION", 157 "fileId": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap", 158 "fileName": "adminprovisioning.hap" 159 } 160 # 构建文件依赖其他文件 161 { 162 "bom-ref": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap", 163 "dependsOn": [ 164 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning_hap/ResourceTable.h", 165 "//out/rk3568/clang_x64/arkcompiler/ets_frontend/es2abc", 166 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning_hap/resources.zip", 167 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning_hap/js_assets.zip", 168 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_hap.metadata", 169 "//out/rk3568/obj/developtools/packing_tool/jar/haptobin_tool.jar", 170 "//out/rk3568/obj/developtools/packing_tool/jar/app_unpacking_tool.jar", 171 "//out/rk3568/obj/developtools/packing_tool/jar", 172 "//out/rk3568/obj/developtools/packing_tool/jar/app_check_tool.jar", 173 "//out/rk3568/clang_x64/obj/arkcompiler/ets_frontend/es2panda/ts2abc.js", 174 "//out/rk3568/obj/developtools/packing_tool/jar/app_packing_tool.jar" 175 ], 176 "relationshipType": "GENERATED_FROM" 177 } 178 # 构建文件来源部件 179 # pkg:gitee/OpenHarmony/applications_admin_provisioning@94d3db73c8492ac0ace0b59e76b0c23b6ca6663f 180 { 181 "bom-ref": "pkg:gitee/OpenHarmony/applications_admin_provisioning@94d3db73c8492ac0ace0b59e76b0c23b6ca6663f", 182 "dependsOn": [ 183 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning_hap/ResourceTable.h", 184 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_app_profile.metadata", 185 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_js_assets.metadata", 186 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_hap.metadata", 187 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning_hap/resources.zip", 188 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_resources.metadata", 189 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_resources/module.json", 190 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning_hap/js_assets.zip", 191 "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap", 192 "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_resources/ResourceTable.h" 193 ], 194 "relationshipType": "GENERATES" 195 } 196 ``` 197 198 --- 199 200 ```json 201 # SPDX2.3 格式 202 # 镜像上文件信息 203 # 以镜像上文件 system/app/com.ohos.adminprovisioning/adminprovisioning.hap 作为起点 204 { 205 "SPDXID": "system/app/com.ohos.adminprovisioning/adminprovisioning.hap", 206 "copyrightText": "NOASSERTION", 207 "fileName": "adminprovisioning.hap" 208 } 209 # 安装到镜像上文件依赖 210 # 此镜像上文件由 //out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap 拷贝产生 211 { 212 "relatedSpdxElement": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap", 213 "relationshipType": "COPY_OF", 214 "spdxElementId": "system/app/com.ohos.adminprovisioning/adminprovisioning.hap" 215 } 216 # 构建生成文件 217 # 构建文件 //out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap 信息 218 { 219 "SPDXID": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap", 220 "copyrightText": "NOASSERTION", 221 "fileName": "adminprovisioning.hap" 222 } 223 # 构建文件依赖其他文件 224 { 225 "relatedSpdxElement": "//out/rk3568/obj/developtools/packing_tool/jar/app_check_tool.jar", 226 "relationshipType": "GENERATED_FROM", 227 "spdxElementId": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap" 228 }, 229 { 230 "relatedSpdxElement": "//out/rk3568/gen/applications/standard/admin_provisioning/adminprovisioning_hap.metadata", 231 "relationshipType": "GENERATED_FROM", 232 "spdxElementId": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap" 233 } ... 234 # 构建文件来源部件 235 # pkg:gitee/OpenHarmony/applications_admin_provisioning@94d3db73c8492ac0ace0b59e76b0c23b6ca6663f 236 { 237 "relatedSpdxElement": "//out/rk3568/obj/applications/standard/admin_provisioning/adminprovisioning.hap", 238 "relationshipType": "GENERATES", 239 "spdxElementId": "pkg:gitee/OpenHarmony/applications_admin_provisioning@94d3db73c8492ac0ace0b59e76b0c23b6ca6663f" 240 } 241 ``` 242 2432. **上游包** 244 245 ```json 246 # sbom 中间态格式 247 # 以 pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615 为例 248 { 249 "bom-ref": "pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615", 250 "compPlatform": "Linux", 251 "downloadLocation": "https://gitee.com/openharmony/third_party_bounds_checking_function/tree/2ae82839ecaaa7d031e66ccbd2076d671acfd615", 252 "group": "OpenHarmony", 253 "licenseDeclared": "NOASSERTION", 254 "name": "third_party_bounds_checking_function", 255 "purl": "pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615", 256 "supplier": "Organization: OpenHarmony", 257 "type": "library", 258 "version": "master" 259 } 260 # 依赖信息 261 # 依赖关系是变体,上游包 ref 为 pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16 262 { 263 "bom-ref": "pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615", 264 "dependsOn": [ 265 "pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16" 266 ], 267 "relationshipType": "VARIANT_OF" 268 } 269 # 上游包信息 270 { 271 "bom-ref": "pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16", 272 "downloadLocation": "https://gitee.com/openeuler/libboundscheck", 273 "licenseConcluded": "Mulan Permissive Software License,Version 2", 274 "name": "openEuler:libboundscheck", 275 "purl": "pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16", 276 "supplier": "NOASSERTION", 277 "type": "library", 278 "version": "v1.1.16" 279 } 280 ``` 281 282 --- 283 284 ```json 285 # SPDX 格式 286 # 以 pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615 为例 287 { 288 "SPDXID": "pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615", 289 "copyrightText": "NOASSERTION", 290 "downloadLocation": "https://gitee.com/openharmony/third_party_bounds_checking_function/tree/2ae82839ecaaa7d031e66ccbd2076d671acfd615", 291 "externalRefs": [ 292 { 293 "referenceLocator": "pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615", 294 "referenceType": "purl" 295 } 296 ], 297 "filesAnalyzed": false, 298 "licenseDeclared": "NOASSERTION", 299 "name": "third_party_bounds_checking_function", 300 "originator": "OpenHarmony", 301 "primaryPackagePurpose": "LIBRARY", 302 "supplier": "Organization: OpenHarmony", 303 "versionInfo": "master" 304 } 305 # 依赖信息 306 # 依赖关系是变体,上游包 ref 为 pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16 307 { 308 "relatedSpdxElement": "pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16", 309 "relationshipType": "VARIANT_OF", 310 "spdxElementId": "pkg:gitee/OpenHarmony/third_party_bounds_checking_function@2ae82839ecaaa7d031e66ccbd2076d671acfd615" 311 } 312 # 上游包信息 313 { 314 "SPDXID": "pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16", 315 "copyrightText": "NOASSERTION", 316 "downloadLocation": "https://gitee.com/openeuler/libboundscheck", 317 "externalRefs": [ 318 { 319 "referenceLocator": "pkg:gitee/upstream/openEuler:libboundscheck@v1.1.16", 320 "referenceType": "purl" 321 } 322 ], 323 "filesAnalyzed": false, 324 "licenseConcluded": "Mulan Permissive Software License,Version 2", 325 "name": "openEuler:libboundscheck", 326 "primaryPackagePurpose": "LIBRARY", 327 "supplier": "NOASSERTION", 328 "versionInfo": "v1.1.16" 329 } 330 ``` 331 3323. **so文件依赖关系** 333 334 ```json 335 # sbom 中间态格式 336 # so 文件信息 337 { 338 "copyrightText": "NOASSERTION", 339 "fileAuthor": "NOASSERTION", 340 "fileId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so", 341 "fileName": "libcj_calendar_manager_ffi.z.so" 342 } 343 # 源文件 344 { 345 "bom-ref": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so", 346 "dependsOn": [ 347 "//applications/standard/calendardata/calendarmanager/cj/src/cj_native_calendar.cpp", 348 "//applications/standard/calendardata/calendarmanager/cj/src/cj_data_share_helper_manager.cpp", 349 "//applications/standard/calendardata/calendarmanager/native/src/calendar_env.cpp", 350 "//applications/standard/calendardata/calendarmanager/cj/src/cj_calendar_manager.cpp", 351 "//applications/standard/calendardata/calendarmanager/native/src/event_filter.cpp", 352 "//applications/standard/calendardata/calendarmanager/cj/src/cj_event_filter.cpp", 353 "//applications/standard/calendardata/calendarmanager/cj/src/cj_native_calendar_manager.cpp", 354 "//applications/standard/calendardata/calendarmanager/cj/src/cj_native_util.cpp", 355 "//applications/standard/calendardata/calendarmanager/cj/src/cj_calendar_env.cpp", 356 "//applications/standard/calendardata/calendarmanager/cj/src/calendar_manager_ffi.cpp", 357 "//applications/standard/calendardata/calendarmanager/cj/src/cj_calendar.cpp" 358 ], 359 "relationshipType": "GENERATED_FROM" 360 } 361 # 静态依赖 362 { 363 "bom-ref": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so", 364 "dependsOn": [ 365 "libclang_rt.builtins.a", 366 "libc++abi.a" 367 ], 368 "relationshipType": "STATIC_LINK" 369 } 370 # 动态依赖 371 { 372 "bom-ref": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so", 373 "dependsOn": [ 374 "//out/rk3568/distributeddatamgr/data_share/libdatashare_common.z.so", 375 "//out/rk3568/ability/ability_runtime/libnapi_base_context.z.so", 376 "libc++.so", 377 "//out/rk3568/arkui/ace_engine/libace_uicontent.z.so", 378 "libc.so", 379 "//out/rk3568/arkui/napi/libcj_bind_ffi.z.so", 380 "//out/rk3568/distributeddatamgr/data_share/libdatashare_consumer.z.so", 381 "//out/rk3568/security/access_token/libprivacy_sdk.z.so", 382 "libm.so", 383 "//out/rk3568/ability/ability_runtime/libability_context_native.z.so", 384 "//out/rk3568/hiviewdfx/hilog/libhilog.so", 385 "libunwind.so", 386 "//out/rk3568/ability/ability_base/libzuri.z.so", 387 "//out/rk3568/ability/ability_runtime/libdata_ability_helper.z.so", 388 "//out/rk3568/arkui/napi/libace_napi.z.so", 389 "//out/rk3568/ability/ability_runtime/libabilitykit_native.z.so", 390 "//out/rk3568/arkui/napi/libcj_bind_native.z.so", 391 "//out/rk3568/security/access_token/libaccesstoken_sdk.z.so", 392 "//out/rk3568/ability/ability_runtime/libability_manager.z.so", 393 "//out/rk3568/ability/ability_base/libwant.z.so", 394 "//out/rk3568/commonlibrary/c_utils/libutils.z.so", 395 "//out/rk3568/ability/ability_runtime/libability_connect_callback_stub.z.so", 396 "//out/rk3568/communication/ipc/libipc_single.z.so", 397 "libdl.so" 398 ], 399 "relationshipType": "DYNAMIC_LINK" 400 } 401 ``` 402 403 --- 404 405 ```json 406 # SPDX 格式 407 # so 文件信息 408 { 409 "SPDXID": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so", 410 "copyrightText": "NOASSERTION", 411 "fileName": "libcj_calendar_manager_ffi.z.so" 412 } 413 # 源文件 414 { 415 "relatedSpdxElement": "//applications/standard/calendardata/calendarmanager/cj/src/cj_calendar.cpp", 416 "relationshipType": "GENERATED_FROM", 417 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 418 }, 419 { 420 "relatedSpdxElement": "//applications/standard/calendardata/calendarmanager/cj/src/cj_native_calendar.cpp", 421 "relationshipType": "GENERATED_FROM", 422 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 423 }, 424 { 425 "relatedSpdxElement": "//applications/standard/calendardata/calendarmanager/native/src/calendar_env.cpp", 426 "relationshipType": "GENERATED_FROM", 427 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 428 }, 429 { 430 "relatedSpdxElement": "//applications/standard/calendardata/calendarmanager/cj/src/cj_event_filter.cpp", 431 "relationshipType": "GENERATED_FROM", 432 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 433 } ... 434 # 静态依赖 435 { 436 "relatedSpdxElement": "libclang_rt.builtins.a", 437 "relationshipType": "STATIC_LINK", 438 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 439 }, 440 { 441 "relatedSpdxElement": "libc++abi.a", 442 "relationshipType": "STATIC_LINK", 443 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 444 } 445 # 动态依赖 446 { 447 "relatedSpdxElement": "//out/rk3568/security/access_token/libaccesstoken_sdk.z.so", 448 "relationshipType": "DYNAMIC_LINK", 449 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 450 }, 451 { 452 "relatedSpdxElement": "//out/rk3568/hiviewdfx/hilog/libhilog.so", 453 "relationshipType": "DYNAMIC_LINK", 454 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 455 }, 456 { 457 "relatedSpdxElement": "//out/rk3568/ability/ability_runtime/libability_context_native.z.so", 458 "relationshipType": "DYNAMIC_LINK", 459 "spdxElementId": "//out/rk3568/applications/calendar_data/libcj_calendar_manager_ffi.z.so" 460 } ... 461 ``` 462 463 464