@cdxgen/cdxgen 13.2.0 → 13.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/README.md +33 -14
  2. package/bin/cdxgen.js +310 -138
  3. package/bin/evinse.js +22 -0
  4. package/bin/repl.js +86 -0
  5. package/bin/sign.js +119 -15
  6. package/bin/tracebom.js +69 -5
  7. package/bin/validate.js +107 -19
  8. package/bin/verify.js +172 -63
  9. package/data/helpers/init.gradle +46 -21
  10. package/data/remediations.json +85 -0
  11. package/data/rules/dependency-sources.yaml +67 -0
  12. package/data/rules/scala-evidence.yaml +115 -0
  13. package/lib/audit/index.js +38 -6
  14. package/lib/cli/bomAssembly.js +105 -15
  15. package/lib/cli/cliOptions.js +93 -1
  16. package/lib/cli/index.js +156 -58
  17. package/lib/cli/jsBom.js +99 -53
  18. package/lib/cli/jvmBom.js +708 -147
  19. package/lib/cli/managedBom.js +415 -224
  20. package/lib/cli/nativeBom.js +264 -44
  21. package/lib/core/activity.js +12 -0
  22. package/lib/core/env.js +22 -15
  23. package/lib/core/fs.js +176 -7
  24. package/lib/core/httpClient.js +159 -24
  25. package/lib/core/metadataProperties.js +97 -0
  26. package/lib/core/pluginRun.js +184 -0
  27. package/lib/core/processTree.js +100 -0
  28. package/lib/core/projectConfig.js +31 -4
  29. package/lib/core/runState.js +39 -0
  30. package/lib/core/toml.js +72 -0
  31. package/lib/ecosystems/asarutils.js +4 -2
  32. package/lib/ecosystems/bunutils.js +274 -108
  33. package/lib/ecosystems/cargoCache.js +231 -8
  34. package/lib/ecosystems/caxa.js +434 -2
  35. package/lib/ecosystems/cmakeResolver.js +76 -21
  36. package/lib/ecosystems/cppBuildContext.js +631 -0
  37. package/lib/ecosystems/cppEvidence.js +399 -51
  38. package/lib/ecosystems/cppIncludeResolver.js +294 -0
  39. package/lib/ecosystems/denoutils.js +93 -66
  40. package/lib/ecosystems/ecosystems.js +1983 -793
  41. package/lib/ecosystems/golem.js +28 -12
  42. package/lib/ecosystems/gradleutils.js +356 -37
  43. package/lib/ecosystems/jsEvidence.js +104 -44
  44. package/lib/ecosystems/kosi.js +31 -7
  45. package/lib/ecosystems/npmutils.js +174 -9
  46. package/lib/ecosystems/parsers-dotnet.js +616 -159
  47. package/lib/ecosystems/parsers-elm.js +46 -28
  48. package/lib/ecosystems/parsers-gleam.js +3 -4
  49. package/lib/ecosystems/parsers-go.js +371 -70
  50. package/lib/ecosystems/parsers-js.js +263 -76
  51. package/lib/ecosystems/parsers-julia.js +2 -3
  52. package/lib/ecosystems/parsers-jvm.js +204 -12
  53. package/lib/ecosystems/parsers-misc.js +929 -216
  54. package/lib/ecosystems/parsers-python.js +167 -24
  55. package/lib/ecosystems/parsers-rust.js +28 -22
  56. package/lib/ecosystems/parsers-terraform.js +1573 -19
  57. package/lib/ecosystems/pythonutils.js +102 -6
  58. package/lib/ecosystems/remote/huggingface.js +3 -0
  59. package/lib/ecosystems/rubyutils.js +1492 -182
  60. package/lib/ecosystems/rusi.js +54 -10
  61. package/lib/ecosystems/sbtutils.js +243 -187
  62. package/lib/ecosystems/scalacliutils.js +342 -0
  63. package/lib/ecosystems/scalasem.js +2618 -0
  64. package/lib/ecosystems/terraformRegistry.js +288 -0
  65. package/lib/ecosystems/utils.js +2 -0
  66. package/lib/ecosystems/vendoredCode.js +156 -0
  67. package/lib/evinser/evinser.js +1008 -191
  68. package/lib/evinser/swiftsem.js +1914 -302
  69. package/lib/helpers/agenticToolutils.js +2 -2
  70. package/lib/helpers/bomSigner.js +1101 -222
  71. package/lib/inventory/aiCollector.js +4 -1
  72. package/lib/inventory/analyzer.js +110 -127
  73. package/lib/inventory/atomUtils.js +703 -43
  74. package/lib/inventory/auditCategories.js +7 -0
  75. package/lib/inventory/buildToolRateLimit.js +144 -0
  76. package/lib/inventory/cacheCommands.js +2 -1
  77. package/lib/inventory/cdxrs.js +103 -12
  78. package/lib/inventory/cmakeBuildDirs.js +254 -0
  79. package/lib/inventory/deps.js +501 -124
  80. package/lib/inventory/depsUtils.js +183 -11
  81. package/lib/inventory/display.js +4 -5
  82. package/lib/inventory/dosai.js +798 -57
  83. package/lib/inventory/dosaiParsers.js +310 -15
  84. package/lib/inventory/dynamic.js +90 -6
  85. package/lib/inventory/evidenceUtils.js +166 -113
  86. package/lib/inventory/fetchBatch.js +690 -55
  87. package/lib/inventory/fetchDiskCache.js +597 -0
  88. package/lib/inventory/forgeEnricher.js +14 -5
  89. package/lib/inventory/jvmLocalRepos.js +917 -0
  90. package/lib/inventory/mcpConfigParser.js +2 -3
  91. package/lib/inventory/parentSelection.js +146 -0
  92. package/lib/inventory/protobom.js +8 -1
  93. package/lib/inventory/purl.js +152 -3
  94. package/lib/inventory/rustFormulationParser.js +3 -4
  95. package/lib/inventory/sbomDocument.js +2 -70
  96. package/lib/inventory/scalaCoords.js +153 -0
  97. package/lib/inventory/source.js +45 -27
  98. package/lib/inventory/spdx.js +101 -0
  99. package/lib/inventory/traceRunner.js +295 -25
  100. package/lib/inventory/tracedCrypto.js +294 -0
  101. package/lib/managers/binary.js +115 -24
  102. package/lib/managers/docker.js +467 -46
  103. package/lib/managers/oci.js +63 -3
  104. package/lib/parsers/cmakeCache.js +69 -0
  105. package/lib/parsers/cmakeLists.js +466 -0
  106. package/lib/parsers/cmakePresets.js +400 -0
  107. package/lib/parsers/compileCommands.js +557 -0
  108. package/lib/parsers/largeJson.js +454 -0
  109. package/lib/parsers/npmrc.js +19 -1
  110. package/lib/parsers/strictJson.js +322 -0
  111. package/lib/parsers/terraformConfig.js +1073 -0
  112. package/lib/parsers/terraformSource.js +652 -0
  113. package/lib/server/server.js +23 -0
  114. package/lib/stages/postgen/introspection/markers.js +1 -1
  115. package/lib/stages/postgen/postgen.js +83 -16
  116. package/lib/stages/postgen/specVersionCompat.js +32 -0
  117. package/lib/validator/bomValidator.js +6 -16
  118. package/lib/validator/index.js +64 -11
  119. package/lib/validator/reporters/console.js +3 -0
  120. package/lib/validator/reporters/json.js +2 -0
  121. package/lib/validator/reporters/sarif.js +7 -0
  122. package/package.json +23 -23
  123. package/types/lib/audit/index.d.ts.map +1 -1
  124. package/types/lib/cli/bomAssembly.d.ts +2 -1
  125. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  126. package/types/lib/cli/cliOptions.d.ts +33 -1
  127. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  128. package/types/lib/cli/index.d.ts.map +1 -1
  129. package/types/lib/cli/jsBom.d.ts.map +1 -1
  130. package/types/lib/cli/jvmBom.d.ts +24 -1
  131. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  132. package/types/lib/cli/managedBom.d.ts +7 -4
  133. package/types/lib/cli/managedBom.d.ts.map +1 -1
  134. package/types/lib/cli/nativeBom.d.ts +3 -1
  135. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  136. package/types/lib/core/activity.d.ts.map +1 -1
  137. package/types/lib/core/env.d.ts +9 -0
  138. package/types/lib/core/env.d.ts.map +1 -1
  139. package/types/lib/core/fs.d.ts +55 -0
  140. package/types/lib/core/fs.d.ts.map +1 -1
  141. package/types/lib/core/httpClient.d.ts +13 -8
  142. package/types/lib/core/httpClient.d.ts.map +1 -1
  143. package/types/lib/core/metadataProperties.d.ts +39 -0
  144. package/types/lib/core/metadataProperties.d.ts.map +1 -0
  145. package/types/lib/core/pluginRun.d.ts +97 -0
  146. package/types/lib/core/pluginRun.d.ts.map +1 -0
  147. package/types/lib/core/processTree.d.ts +36 -0
  148. package/types/lib/core/processTree.d.ts.map +1 -0
  149. package/types/lib/core/projectConfig.d.ts +6 -2
  150. package/types/lib/core/projectConfig.d.ts.map +1 -1
  151. package/types/lib/core/runState.d.ts +29 -0
  152. package/types/lib/core/runState.d.ts.map +1 -0
  153. package/types/lib/core/toml.d.ts +20 -0
  154. package/types/lib/core/toml.d.ts.map +1 -0
  155. package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
  156. package/types/lib/ecosystems/bunutils.d.ts +12 -5
  157. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  158. package/types/lib/ecosystems/cargoCache.d.ts +12 -0
  159. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
  160. package/types/lib/ecosystems/caxa.d.ts +14 -0
  161. package/types/lib/ecosystems/caxa.d.ts.map +1 -1
  162. package/types/lib/ecosystems/cmakeResolver.d.ts +28 -3
  163. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  164. package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
  165. package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
  166. package/types/lib/ecosystems/cppEvidence.d.ts +17 -1
  167. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  168. package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
  169. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
  170. package/types/lib/ecosystems/denoutils.d.ts +9 -3
  171. package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
  172. package/types/lib/ecosystems/ecosystems.d.ts +62 -13
  173. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  174. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  175. package/types/lib/ecosystems/gradleutils.d.ts +70 -4
  176. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  177. package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
  178. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  179. package/types/lib/ecosystems/kosi.d.ts +13 -0
  180. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  181. package/types/lib/ecosystems/npmutils.d.ts +57 -0
  182. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  183. package/types/lib/ecosystems/parsers-dotnet.d.ts +118 -4
  184. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  185. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
  186. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
  187. package/types/lib/ecosystems/parsers-go.d.ts +54 -2
  188. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  189. package/types/lib/ecosystems/parsers-js.d.ts +16 -5
  190. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  191. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
  192. package/types/lib/ecosystems/parsers-jvm.d.ts +46 -1
  193. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  194. package/types/lib/ecosystems/parsers-misc.d.ts +70 -4
  195. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  196. package/types/lib/ecosystems/parsers-python.d.ts +53 -3
  197. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  198. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  199. package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
  200. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
  201. package/types/lib/ecosystems/pythonutils.d.ts +27 -2
  202. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  203. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  204. package/types/lib/ecosystems/rubyutils.d.ts +164 -3
  205. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  206. package/types/lib/ecosystems/rusi.d.ts +13 -0
  207. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  208. package/types/lib/ecosystems/sbtutils.d.ts +88 -2
  209. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
  210. package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
  211. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
  212. package/types/lib/ecosystems/scalasem.d.ts +311 -0
  213. package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
  214. package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
  215. package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
  216. package/types/lib/ecosystems/utils.d.ts +2 -2
  217. package/types/lib/ecosystems/utils.d.ts.map +1 -1
  218. package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
  219. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
  220. package/types/lib/evinser/evinser.d.ts +132 -15
  221. package/types/lib/evinser/evinser.d.ts.map +1 -1
  222. package/types/lib/evinser/swiftsem.d.ts +280 -15
  223. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  224. package/types/lib/helpers/bomSigner.d.ts +182 -13
  225. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  226. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  227. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  228. package/types/lib/inventory/atomUtils.d.ts +219 -5
  229. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  230. package/types/lib/inventory/auditCategories.d.ts +3 -0
  231. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  232. package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
  233. package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
  234. package/types/lib/inventory/cacheCommands.d.ts +2 -1
  235. package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
  236. package/types/lib/inventory/cdxrs.d.ts +8 -3
  237. package/types/lib/inventory/cdxrs.d.ts.map +1 -1
  238. package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
  239. package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
  240. package/types/lib/inventory/deps.d.ts +59 -1
  241. package/types/lib/inventory/deps.d.ts.map +1 -1
  242. package/types/lib/inventory/depsUtils.d.ts +15 -0
  243. package/types/lib/inventory/depsUtils.d.ts.map +1 -1
  244. package/types/lib/inventory/display.d.ts.map +1 -1
  245. package/types/lib/inventory/dosai.d.ts +121 -9
  246. package/types/lib/inventory/dosai.d.ts.map +1 -1
  247. package/types/lib/inventory/dosaiParsers.d.ts +53 -7
  248. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  249. package/types/lib/inventory/dynamic.d.ts +10 -0
  250. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  251. package/types/lib/inventory/evidenceUtils.d.ts +19 -4
  252. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  253. package/types/lib/inventory/fetchBatch.d.ts +83 -14
  254. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  255. package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
  256. package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
  257. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  258. package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
  259. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
  260. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  261. package/types/lib/inventory/parentSelection.d.ts +34 -0
  262. package/types/lib/inventory/parentSelection.d.ts.map +1 -0
  263. package/types/lib/inventory/plugins.d.ts.map +1 -1
  264. package/types/lib/inventory/protobom.d.ts.map +1 -1
  265. package/types/lib/inventory/purl.d.ts +71 -2
  266. package/types/lib/inventory/purl.d.ts.map +1 -1
  267. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  268. package/types/lib/inventory/sbomDocument.d.ts.map +1 -1
  269. package/types/lib/inventory/scalaCoords.d.ts +80 -0
  270. package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
  271. package/types/lib/inventory/source.d.ts.map +1 -1
  272. package/types/lib/inventory/spdx.d.ts +9 -0
  273. package/types/lib/inventory/spdx.d.ts.map +1 -1
  274. package/types/lib/inventory/traceRunner.d.ts +59 -1
  275. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  276. package/types/lib/inventory/tracedCrypto.d.ts +42 -0
  277. package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
  278. package/types/lib/managers/binary.d.ts +30 -1
  279. package/types/lib/managers/binary.d.ts.map +1 -1
  280. package/types/lib/managers/docker.d.ts +29 -0
  281. package/types/lib/managers/docker.d.ts.map +1 -1
  282. package/types/lib/managers/oci.d.ts +17 -1
  283. package/types/lib/managers/oci.d.ts.map +1 -1
  284. package/types/lib/parsers/cmakeCache.d.ts +16 -0
  285. package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
  286. package/types/lib/parsers/cmakeLists.d.ts +77 -0
  287. package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
  288. package/types/lib/parsers/cmakePresets.d.ts +78 -0
  289. package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
  290. package/types/lib/parsers/compileCommands.d.ts +115 -0
  291. package/types/lib/parsers/compileCommands.d.ts.map +1 -0
  292. package/types/lib/parsers/largeJson.d.ts +52 -0
  293. package/types/lib/parsers/largeJson.d.ts.map +1 -0
  294. package/types/lib/parsers/npmrc.d.ts +5 -0
  295. package/types/lib/parsers/npmrc.d.ts.map +1 -1
  296. package/types/lib/parsers/strictJson.d.ts +46 -0
  297. package/types/lib/parsers/strictJson.d.ts.map +1 -0
  298. package/types/lib/parsers/terraformConfig.d.ts +70 -0
  299. package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
  300. package/types/lib/parsers/terraformSource.d.ts +66 -0
  301. package/types/lib/parsers/terraformSource.d.ts.map +1 -0
  302. package/types/lib/server/server.d.ts.map +1 -1
  303. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  304. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  305. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  306. package/types/lib/validator/index.d.ts +18 -1
  307. package/types/lib/validator/index.d.ts.map +1 -1
  308. package/types/lib/validator/reporters/console.d.ts.map +1 -1
  309. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  310. package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
  311. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
@@ -19,17 +19,205 @@ import {
19
19
  import { build } from "@cdxgen/cdx-purl";
20
20
 
21
21
  import { DEBUG_MODE } from "../core/activity.js";
22
- import { safeExistsSync } from "../core/fs.js";
22
+ import { getAllFiles, safeExistsSync } from "../core/fs.js";
23
+ import { thoughtLog } from "../core/logger.js";
23
24
  import { CPP_STD_MODULES } from "../core/state.js";
24
25
  import { findAppModules } from "../inventory/atomUtils.js";
26
+ import { cmakeBuildDirCandidates } from "../inventory/cmakeBuildDirs.js";
25
27
  import { getOSPackageForFile } from "../inventory/osPackageResolver.js";
26
28
  import { locateGenericPackage } from "../inventory/purl.js";
29
+ import {
30
+ createIncludeAttributor,
31
+ parseCIncludeSlices,
32
+ } from "./cppIncludeResolver.js";
27
33
  import {
28
34
  parseCmakeLikeFile,
29
35
  parseCUsageSlice,
30
36
  parseXmakeRequiresLock,
31
37
  } from "./parsers-misc.js";
32
38
 
39
+ /**
40
+ * Headers of the C standard library (C89 to C23) and of POSIX and the common
41
+ * system interfaces. They come with the C library or the operating system: a
42
+ * component only when an OS package provides them, never a generic one.
43
+ */
44
+ const C_SYSTEM_HEADERS = new Set([
45
+ "assert.h",
46
+ "complex.h",
47
+ "ctype.h",
48
+ "errno.h",
49
+ "fenv.h",
50
+ "float.h",
51
+ "inttypes.h",
52
+ "iso646.h",
53
+ "limits.h",
54
+ "locale.h",
55
+ "math.h",
56
+ "setjmp.h",
57
+ "signal.h",
58
+ "stdalign.h",
59
+ "stdarg.h",
60
+ "stdatomic.h",
61
+ "stdbit.h",
62
+ "stdbool.h",
63
+ "stdckdint.h",
64
+ "stddef.h",
65
+ "stdint.h",
66
+ "stdio.h",
67
+ "stdlib.h",
68
+ "stdnoreturn.h",
69
+ "string.h",
70
+ "tgmath.h",
71
+ "threads.h",
72
+ "time.h",
73
+ "uchar.h",
74
+ "wchar.h",
75
+ "wctype.h",
76
+ "aio.h",
77
+ "alloca.h",
78
+ "arpa/inet.h",
79
+ "cpio.h",
80
+ "dirent.h",
81
+ "dlfcn.h",
82
+ "endian.h",
83
+ "err.h",
84
+ "execinfo.h",
85
+ "fcntl.h",
86
+ "fmtmsg.h",
87
+ "fnmatch.h",
88
+ "ftw.h",
89
+ "getopt.h",
90
+ "glob.h",
91
+ "grp.h",
92
+ "iconv.h",
93
+ "ifaddrs.h",
94
+ "langinfo.h",
95
+ "libgen.h",
96
+ "libintl.h",
97
+ "malloc.h",
98
+ "memory.h",
99
+ "monetary.h",
100
+ "mqueue.h",
101
+ "ndbm.h",
102
+ "net/if.h",
103
+ "netdb.h",
104
+ "netinet/in.h",
105
+ "netinet/tcp.h",
106
+ "nl_types.h",
107
+ "poll.h",
108
+ "pthread.h",
109
+ "pwd.h",
110
+ "regex.h",
111
+ "sched.h",
112
+ "search.h",
113
+ "semaphore.h",
114
+ "spawn.h",
115
+ "strings.h",
116
+ "stropts.h",
117
+ "sys/ioctl.h",
118
+ "sys/ipc.h",
119
+ "sys/mman.h",
120
+ "sys/msg.h",
121
+ "sys/param.h",
122
+ "sys/resource.h",
123
+ "sys/select.h",
124
+ "sys/sem.h",
125
+ "sys/shm.h",
126
+ "sys/socket.h",
127
+ "sys/stat.h",
128
+ "sys/statvfs.h",
129
+ "sys/syscall.h",
130
+ "sys/sysctl.h",
131
+ "sys/time.h",
132
+ "sys/times.h",
133
+ "sys/types.h",
134
+ "sys/uio.h",
135
+ "sys/un.h",
136
+ "sys/utsname.h",
137
+ "sys/wait.h",
138
+ "syslog.h",
139
+ "tar.h",
140
+ "termios.h",
141
+ "ucontext.h",
142
+ "ulimit.h",
143
+ "unistd.h",
144
+ "utime.h",
145
+ "utmpx.h",
146
+ "wordexp.h",
147
+ ]);
148
+
149
+ /**
150
+ * Add the symbols a file uses to a component's `internal:ImportedSymbols`,
151
+ * keeping every other property and the symbols already recorded.
152
+ *
153
+ * @param {Object} apkg Component to enrich
154
+ * @param {string[]} symbols Symbol names
155
+ */
156
+ function mergeImportedSymbols(apkg, symbols) {
157
+ apkg.properties = apkg.properties || [];
158
+ const prop = apkg.properties.find(
159
+ (p) => p.name === "internal:ImportedSymbols",
160
+ );
161
+ if (prop) {
162
+ prop.value = Array.from(new Set([...prop.value.split("|"), ...symbols]))
163
+ .sort()
164
+ .join("|");
165
+ } else {
166
+ apkg.properties.push({
167
+ name: "internal:ImportedSymbols",
168
+ value: symbols.join("|"),
169
+ });
170
+ }
171
+ }
172
+
173
+ /**
174
+ * The file name extensions of the C and C++ sources, headers and module
175
+ * units atom's C frontend parses. The search ignores case, so this also
176
+ * covers `.C`, `.H` and the upper-case Windows spellings.
177
+ */
178
+ const CPP_SOURCE_EXTENSIONS = [
179
+ "c",
180
+ "cc",
181
+ "cpp",
182
+ "cxx",
183
+ "c++",
184
+ "h",
185
+ "hh",
186
+ "hpp",
187
+ "hxx",
188
+ "h++",
189
+ "h.in",
190
+ "i",
191
+ "inl",
192
+ "ipp",
193
+ "tcc",
194
+ "tmh",
195
+ "ccm",
196
+ "cppm",
197
+ "cxxm",
198
+ "c++m",
199
+ "ixx",
200
+ "mxx",
201
+ ];
202
+
203
+ /**
204
+ * Whether a directory holds C or C++ sources for atom to parse.
205
+ *
206
+ * The search skips the directories the manifest searches skip, such as
207
+ * node_modules and dot directories, and honours the exclude patterns, so the
208
+ * sources of a native npm addon do not count.
209
+ *
210
+ * @param {string} src directory
211
+ * @param {Object} options CLI options
212
+ * @returns {boolean} true when the directory holds at least one C or C++ file
213
+ */
214
+ export function hasCppSources(src, options = {}) {
215
+ return (
216
+ getAllFiles(src, `**/*.{${CPP_SOURCE_EXTENSIONS.join(",")}}`, options)
217
+ .length > 0
218
+ );
219
+ }
220
+
33
221
  /**
34
222
  * Method to find c/c++ modules by collecting usages with atom
35
223
  *
@@ -37,8 +225,18 @@ import {
37
225
  * @param {object} options Command line options
38
226
  * @param {array} osPkgsList Array of OS pacakges represented as components
39
227
  * @param {array} epkgList Existing packages list
228
+ * @param {function(string): boolean} [isFirstPartyHeader] Whether an
229
+ * included header is the project's own (found under the project root or
230
+ * one of its own include directories, outside any dependency's sources);
231
+ * such a header is not a component
40
232
  */
41
- export function getCppModules(src, options, osPkgsList, epkgList) {
233
+ export function getCppModules(
234
+ src,
235
+ options,
236
+ osPkgsList,
237
+ epkgList,
238
+ isFirstPartyHeader = undefined,
239
+ ) {
42
240
  // Generic is the type to use where the package registry could not be located
43
241
  const pkgType = "generic";
44
242
  const pkgList = [];
@@ -48,9 +246,21 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
48
246
  let parentComponent;
49
247
  const dependsOn = new Set();
50
248
 
249
+ // Components from CMake and Conan carry no group: the key spells a missing
250
+ // group the same way on insert and on lookup.
251
+ const epkgKey = (group, name) => `${group || ""}/${name}`;
51
252
  (epkgList || []).forEach((p) => {
52
- epkgMap[`${p.group}/${p.name}`] = p;
253
+ epkgMap[epkgKey(p.group, p.name)] = p;
53
254
  });
255
+ // Attributes a header from the file its include resolved to, when atom
256
+ // names that file (atom 4 and later)
257
+ const attributeInclude = createIncludeAttributor({
258
+ src,
259
+ components: epkgList || [],
260
+ buildDirs: cmakeBuildDirCandidates(src, options),
261
+ isFirstPartyHeader,
262
+ });
263
+ const vcpkgPorts = attributeInclude.vcpkgPorts();
54
264
  // Let's look for any vcpkg.json file to tell us about the directory we're scanning
55
265
  // users can use this file to give us a clue even if they do not use vcpkg library manager
56
266
  if (safeExistsSync(join(src, "vcpkg.json"))) {
@@ -106,21 +316,23 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
106
316
  // Is this a dependency we haven't seen before including the all lower and upper case version?
107
317
  if (
108
318
  avcpkgName &&
109
- !epkgMap[`/${avcpkgName}`] &&
110
- !epkgMap[`/${avcpkgName.toLowerCase()}`] &&
111
- !epkgMap[`/${avcpkgName.toUpperCase()}`]
319
+ !epkgMap[epkgKey("", avcpkgName)] &&
320
+ !epkgMap[epkgKey("", avcpkgName.toLowerCase())] &&
321
+ !epkgMap[epkgKey("", avcpkgName.toUpperCase())]
112
322
  ) {
323
+ // the version vcpkg installed, when the build tree has the port
324
+ const installed = vcpkgPorts.get(avcpkgName.toLowerCase());
113
325
  const pkgPurl = build({
114
326
  type: pkgType,
115
327
  namespace: "" || null,
116
328
  name: avcpkgName,
117
- version: "" || null,
329
+ version: installed?.version || null,
118
330
  });
119
331
  const apkg = {
120
332
  group: "",
121
333
  name: avcpkgName,
122
334
  type: pkgType,
123
- version: "",
335
+ version: installed?.version || "",
124
336
  purl: pkgPurl,
125
337
  scope,
126
338
  "bom-ref": decodeURIComponent(pkgPurl),
@@ -129,6 +341,9 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
129
341
  ...(vcpkgFeatures
130
342
  ? [{ name: "cdx:vcpkg:features", value: vcpkgFeatures }]
131
343
  : []),
344
+ ...(installed
345
+ ? [{ name: "cdx:vcpkg:triplet", value: installed.triplet }]
346
+ : []),
132
347
  ],
133
348
  evidence: {
134
349
  identity: {
@@ -195,7 +410,7 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
195
410
  if (DEBUG_MODE) {
196
411
  console.log("Re-using existing slices file", options.usagesSlicesFile);
197
412
  }
198
- } else {
413
+ } else if (hasCppSources(src, options)) {
199
414
  sliceData = findAppModules(
200
415
  src,
201
416
  options.deep ? "c" : "h",
@@ -203,11 +418,125 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
203
418
  options.usagesSlicesFile,
204
419
  options,
205
420
  );
421
+ } else {
422
+ thoughtLog(
423
+ `There are no C or C++ sources at '${src}', so atom usages has nothing to read.`,
424
+ );
425
+ sliceData = [];
206
426
  }
207
427
  const usageData = parseCUsageSlice(sliceData);
208
- for (let afile of Object.keys(usageData)) {
428
+ const includeInfo = parseCIncludeSlices(sliceData);
429
+ const osComponents = new Map();
430
+ const addedRefs = new Set();
431
+ // The component a resolved include belongs to, and whether it is already
432
+ // listed (a dependency or vendored directory, a declared vcpkg port, a Conan
433
+ // package the lock file named)
434
+ const includeComponents = new Map();
435
+ const listedNamed = (name, purlType) =>
436
+ [...(epkgList || []), ...pkgList].find(
437
+ (p) =>
438
+ p.name?.toLowerCase() === name.toLowerCase() &&
439
+ (!purlType || `${p.purl || ""}`.startsWith(`pkg:${purlType}/`)),
440
+ );
441
+ const componentForInclude = (target) => {
442
+ if (target.kind === "component") {
443
+ return { component: target.component, listed: true };
444
+ }
445
+ let coords;
446
+ if (target.kind === "os") {
447
+ coords = {
448
+ name: target.pkgInfo.name,
449
+ version: target.pkgInfo.version || "",
450
+ purl: target.pkgInfo.purl,
451
+ technique: "filename",
452
+ };
453
+ } else if (target.kind === "vcpkg") {
454
+ const declared = listedNamed(target.port, pkgType);
455
+ if (declared) {
456
+ // already in the list: declared in vcpkg.json, or given by the caller
457
+ return { component: declared, listed: true };
458
+ }
459
+ coords = {
460
+ name: target.port,
461
+ version: target.version,
462
+ purl: build({
463
+ type: pkgType,
464
+ name: target.port,
465
+ version: target.version || null,
466
+ }),
467
+ properties: [{ name: "cdx:vcpkg:triplet", value: target.triplet }],
468
+ technique: "manifest-analysis",
469
+ };
470
+ } else {
471
+ const locked = listedNamed(target.name, "conan");
472
+ if (locked) {
473
+ return { component: locked, listed: true };
474
+ }
475
+ coords = {
476
+ name: target.name,
477
+ version: target.version,
478
+ purl: build({
479
+ type: "conan",
480
+ name: target.name,
481
+ version: target.version || null,
482
+ }),
483
+ technique: "manifest-analysis",
484
+ };
485
+ }
486
+ const ref = decodeURIComponent(
487
+ coords.purl || `${coords.name}@${coords.version}`,
488
+ );
489
+ let component = includeComponents.get(ref);
490
+ if (!component) {
491
+ component = {
492
+ name: coords.name,
493
+ version: coords.version,
494
+ type: "library",
495
+ purl: coords.purl,
496
+ "bom-ref": ref,
497
+ properties: coords.properties || [],
498
+ evidence: {
499
+ identity: {
500
+ field: "purl",
501
+ confidence: 0.8,
502
+ methods: [
503
+ {
504
+ technique: coords.technique,
505
+ confidence: 0.8,
506
+ value: "Resolved include file",
507
+ },
508
+ ],
509
+ },
510
+ },
511
+ };
512
+ includeComponents.set(ref, component);
513
+ }
514
+ return { component, listed: false };
515
+ };
516
+ const symbolsOf = (key, header) =>
517
+ Array.from(
518
+ new Set([
519
+ ...(usageData[key] || []),
520
+ ...(includeInfo.get(key)?.symbols || []),
521
+ ]),
522
+ )
523
+ .filter(
524
+ (v) =>
525
+ !v.startsWith("<") &&
526
+ !v.startsWith("__") &&
527
+ v !== "main" &&
528
+ !v.includes("anonymous_") &&
529
+ !v.includes(header),
530
+ )
531
+ .map((v) => v.split(":")[0])
532
+ .sort();
533
+ // Only includes name headers; the other keys are the project's own source
534
+ // files, with the symbols they use
535
+ for (const sliceKey of Object.keys(usageData).filter((k) =>
536
+ includeInfo.has(k),
537
+ )) {
209
538
  // Normalize windows separator
210
- afile = afile.replace("..\\", "").replace(/\\/g, "/");
539
+ const afile = sliceKey.replace("..\\", "").replace(/\\/g, "/");
211
540
  const fileName = basename(afile);
212
541
  if (!fileName?.length) {
213
542
  continue;
@@ -235,13 +564,58 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
235
564
  if (CPP_STD_MODULES.includes(name)) {
236
565
  continue;
237
566
  }
238
- let apkg = getOSPackageForFile(afile, osPkgsList) ||
239
- epkgMap[`${group}/${name}`] || {
567
+ // The file the include resolved to names its package exactly
568
+ const resolvedFiles = includeInfo.get(sliceKey)?.paths;
569
+ const target = resolvedFiles?.size
570
+ ? attributeInclude(resolvedFiles)
571
+ : undefined;
572
+ if (target?.kind === "first-party") {
573
+ continue;
574
+ }
575
+ if (target) {
576
+ const { component, listed } = componentForInclude(target);
577
+ const usymbols = symbolsOf(sliceKey, afile);
578
+ if (usymbols.length) {
579
+ mergeImportedSymbols(component, usymbols);
580
+ }
581
+ if (!listed && !addedRefs.has(component["bom-ref"])) {
582
+ pkgList.push(component);
583
+ addedRefs.add(component["bom-ref"]);
584
+ }
585
+ dependsOn.add(component["bom-ref"]);
586
+ continue;
587
+ }
588
+ if (isFirstPartyHeader?.(afile)) {
589
+ continue;
590
+ }
591
+ // The OS package list is shared by every header: a component taken from it
592
+ // is a copy, so the internal:PkgProvides the next header is matched against
593
+ // stays intact. A component the caller already listed is enriched in place
594
+ // and not listed again.
595
+ const osPkg = getOSPackageForFile(afile, osPkgsList);
596
+ if (!osPkg && C_SYSTEM_HEADERS.has(afile)) {
597
+ continue;
598
+ }
599
+ const listedPkg = osPkg ? undefined : epkgMap[epkgKey(group, name)];
600
+ let apkg;
601
+ if (osPkg) {
602
+ const osRef = osPkg["bom-ref"] || osPkg.purl || osPkg.name;
603
+ apkg = osComponents.get(osRef);
604
+ if (!apkg) {
605
+ apkg = {
606
+ ...osPkg,
607
+ properties: (osPkg.properties || []).map((prop) => ({ ...prop })),
608
+ };
609
+ osComponents.set(osRef, apkg);
610
+ }
611
+ } else {
612
+ apkg = listedPkg || {
240
613
  name,
241
614
  group,
242
615
  version: "",
243
616
  type: pkgType,
244
617
  };
618
+ }
245
619
  // If this is a relative file, there is a good chance we can reuse the project group
246
620
  if (!afile.startsWith(_sep) && !group.length) {
247
621
  group = options.projectGroup || "";
@@ -279,48 +653,22 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
279
653
  };
280
654
  apkg["bom-ref"] = decodeURIComponent(apkg["purl"]);
281
655
  }
282
- if (usageData[afile]) {
283
- const usymbols = Array.from(usageData[afile])
284
- .filter(
285
- (v) =>
286
- !v.startsWith("<") &&
287
- !v.startsWith("__") &&
288
- v !== "main" &&
289
- !v.includes("anonymous_") &&
290
- !v.includes(afile),
291
- )
292
- .map((v) => v.split(":")[0])
293
- .sort();
294
- if (!apkg["properties"] && usymbols.length) {
295
- apkg["properties"] = [
296
- { name: "internal:ImportedSymbols", value: usymbols.join("|") },
297
- ];
298
- } else {
299
- apkg["properties"] = [];
300
- }
301
- const newProps = [];
302
- let symbolsPropertyFound = false;
303
- for (const prop of apkg["properties"]) {
304
- if (prop.name === "internal:ImportedSymbols") {
305
- symbolsPropertyFound = true;
306
- let existingSymbols = prop.value.split("|");
307
- existingSymbols = existingSymbols.concat(usymbols);
308
- prop.value = Array.from(new Set(existingSymbols)).sort().join("|");
309
- }
310
- newProps.push(prop);
311
- }
312
- if (!symbolsPropertyFound && usymbols.length) {
313
- apkg["properties"].push({
314
- name: "internal:ImportedSymbols",
315
- value: usymbols.join("|"),
316
- });
317
- }
318
- apkg["properties"] = newProps;
656
+ const usymbols = symbolsOf(sliceKey, afile);
657
+ if (usymbols.length) {
658
+ mergeImportedSymbols(apkg, usymbols);
319
659
  }
320
660
  // At this point, we have a package but we don't know what it's called
321
661
  // So let's try to locate this generic package using some heuristics
322
662
  apkg = locateGenericPackage(apkg);
323
- if (!pkgAddedMap[name]) {
663
+ if (listedPkg) {
664
+ dependsOn.add(apkg["bom-ref"]);
665
+ } else if (osPkg) {
666
+ if (!addedRefs.has(apkg["bom-ref"])) {
667
+ pkgList.push(apkg);
668
+ dependsOn.add(apkg["bom-ref"]);
669
+ addedRefs.add(apkg["bom-ref"]);
670
+ }
671
+ } else if (!pkgAddedMap[name]) {
324
672
  pkgList.push(apkg);
325
673
  dependsOn.add(apkg["bom-ref"]);
326
674
  pkgAddedMap[name] = true;