@cdxgen/cdxgen 13.3.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 (255) hide show
  1. package/README.md +9 -6
  2. package/bin/cdxgen.js +90 -26
  3. package/bin/evinse.js +18 -1
  4. package/bin/repl.js +86 -0
  5. package/bin/sign.js +45 -15
  6. package/bin/tracebom.js +5 -1
  7. package/bin/validate.js +84 -18
  8. package/bin/verify.js +155 -86
  9. package/data/helpers/init.gradle +46 -21
  10. package/data/remediations.json +61 -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/index.js +113 -54
  15. package/lib/cli/jsBom.js +50 -29
  16. package/lib/cli/jvmBom.js +665 -138
  17. package/lib/cli/managedBom.js +320 -200
  18. package/lib/cli/nativeBom.js +139 -30
  19. package/lib/core/activity.js +12 -0
  20. package/lib/core/env.js +17 -9
  21. package/lib/core/fs.js +3 -2
  22. package/lib/core/httpClient.js +159 -24
  23. package/lib/core/pluginRun.js +184 -0
  24. package/lib/core/processTree.js +100 -0
  25. package/lib/core/runState.js +39 -0
  26. package/lib/core/toml.js +72 -0
  27. package/lib/ecosystems/asarutils.js +4 -2
  28. package/lib/ecosystems/bunutils.js +5 -7
  29. package/lib/ecosystems/cargoCache.js +231 -8
  30. package/lib/ecosystems/cmakeResolver.js +10 -21
  31. package/lib/ecosystems/cppBuildContext.js +631 -0
  32. package/lib/ecosystems/cppEvidence.js +337 -22
  33. package/lib/ecosystems/cppIncludeResolver.js +294 -0
  34. package/lib/ecosystems/denoutils.js +93 -66
  35. package/lib/ecosystems/ecosystems.js +1967 -788
  36. package/lib/ecosystems/golem.js +28 -12
  37. package/lib/ecosystems/gradleutils.js +314 -30
  38. package/lib/ecosystems/jsEvidence.js +85 -24
  39. package/lib/ecosystems/kosi.js +21 -4
  40. package/lib/ecosystems/npmutils.js +64 -0
  41. package/lib/ecosystems/parsers-dotnet.js +567 -151
  42. package/lib/ecosystems/parsers-elm.js +46 -28
  43. package/lib/ecosystems/parsers-gleam.js +3 -4
  44. package/lib/ecosystems/parsers-go.js +324 -61
  45. package/lib/ecosystems/parsers-js.js +92 -26
  46. package/lib/ecosystems/parsers-julia.js +2 -3
  47. package/lib/ecosystems/parsers-jvm.js +204 -12
  48. package/lib/ecosystems/parsers-misc.js +182 -55
  49. package/lib/ecosystems/parsers-python.js +141 -10
  50. package/lib/ecosystems/parsers-rust.js +4 -4
  51. package/lib/ecosystems/parsers-terraform.js +1573 -19
  52. package/lib/ecosystems/pythonutils.js +102 -6
  53. package/lib/ecosystems/remote/huggingface.js +3 -0
  54. package/lib/ecosystems/rubyutils.js +67 -17
  55. package/lib/ecosystems/rusi.js +22 -9
  56. package/lib/ecosystems/sbtutils.js +243 -187
  57. package/lib/ecosystems/scalacliutils.js +342 -0
  58. package/lib/ecosystems/scalasem.js +2618 -0
  59. package/lib/ecosystems/terraformRegistry.js +288 -0
  60. package/lib/ecosystems/utils.js +2 -0
  61. package/lib/ecosystems/vendoredCode.js +156 -0
  62. package/lib/evinser/evinser.js +578 -69
  63. package/lib/helpers/agenticToolutils.js +2 -2
  64. package/lib/helpers/bomSigner.js +576 -128
  65. package/lib/inventory/aiCollector.js +4 -1
  66. package/lib/inventory/analyzer.js +110 -127
  67. package/lib/inventory/atomUtils.js +171 -48
  68. package/lib/inventory/auditCategories.js +7 -0
  69. package/lib/inventory/buildToolRateLimit.js +144 -0
  70. package/lib/inventory/cacheCommands.js +2 -1
  71. package/lib/inventory/cmakeBuildDirs.js +254 -0
  72. package/lib/inventory/deps.js +501 -124
  73. package/lib/inventory/dosai.js +248 -44
  74. package/lib/inventory/dosaiParsers.js +310 -15
  75. package/lib/inventory/dynamic.js +52 -6
  76. package/lib/inventory/evidenceUtils.js +154 -109
  77. package/lib/inventory/fetchBatch.js +574 -38
  78. package/lib/inventory/fetchDiskCache.js +597 -0
  79. package/lib/inventory/forgeEnricher.js +14 -5
  80. package/lib/inventory/jvmLocalRepos.js +917 -0
  81. package/lib/inventory/mcpConfigParser.js +2 -3
  82. package/lib/inventory/parentSelection.js +146 -0
  83. package/lib/inventory/rustFormulationParser.js +3 -4
  84. package/lib/inventory/scalaCoords.js +153 -0
  85. package/lib/inventory/source.js +8 -8
  86. package/lib/inventory/spdx.js +101 -0
  87. package/lib/inventory/traceRunner.js +88 -7
  88. package/lib/inventory/tracedCrypto.js +294 -0
  89. package/lib/managers/docker.js +33 -32
  90. package/lib/managers/oci.js +24 -2
  91. package/lib/parsers/cmakeCache.js +69 -0
  92. package/lib/parsers/cmakeLists.js +16 -2
  93. package/lib/parsers/cmakePresets.js +400 -0
  94. package/lib/parsers/compileCommands.js +557 -0
  95. package/lib/parsers/strictJson.js +322 -0
  96. package/lib/parsers/terraformConfig.js +1073 -0
  97. package/lib/parsers/terraformSource.js +652 -0
  98. package/lib/server/server.js +23 -0
  99. package/lib/stages/postgen/introspection/markers.js +1 -1
  100. package/lib/stages/postgen/postgen.js +15 -1
  101. package/lib/stages/postgen/specVersionCompat.js +32 -0
  102. package/lib/validator/index.js +25 -10
  103. package/lib/validator/reporters/json.js +1 -0
  104. package/package.json +21 -21
  105. package/types/lib/audit/index.d.ts.map +1 -1
  106. package/types/lib/cli/index.d.ts.map +1 -1
  107. package/types/lib/cli/jsBom.d.ts.map +1 -1
  108. package/types/lib/cli/jvmBom.d.ts +24 -1
  109. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  110. package/types/lib/cli/managedBom.d.ts +7 -4
  111. package/types/lib/cli/managedBom.d.ts.map +1 -1
  112. package/types/lib/cli/nativeBom.d.ts +3 -1
  113. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  114. package/types/lib/core/activity.d.ts.map +1 -1
  115. package/types/lib/core/env.d.ts +9 -0
  116. package/types/lib/core/env.d.ts.map +1 -1
  117. package/types/lib/core/fs.d.ts.map +1 -1
  118. package/types/lib/core/httpClient.d.ts +13 -8
  119. package/types/lib/core/httpClient.d.ts.map +1 -1
  120. package/types/lib/core/pluginRun.d.ts +97 -0
  121. package/types/lib/core/pluginRun.d.ts.map +1 -0
  122. package/types/lib/core/processTree.d.ts +36 -0
  123. package/types/lib/core/processTree.d.ts.map +1 -0
  124. package/types/lib/core/runState.d.ts +29 -0
  125. package/types/lib/core/runState.d.ts.map +1 -0
  126. package/types/lib/core/toml.d.ts +20 -0
  127. package/types/lib/core/toml.d.ts.map +1 -0
  128. package/types/lib/ecosystems/asarutils.d.ts.map +1 -1
  129. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  130. package/types/lib/ecosystems/cargoCache.d.ts +12 -0
  131. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -1
  132. package/types/lib/ecosystems/cmakeResolver.d.ts +5 -3
  133. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  134. package/types/lib/ecosystems/cppBuildContext.d.ts +55 -0
  135. package/types/lib/ecosystems/cppBuildContext.d.ts.map +1 -0
  136. package/types/lib/ecosystems/cppEvidence.d.ts +18 -2
  137. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  138. package/types/lib/ecosystems/cppIncludeResolver.d.ts +92 -0
  139. package/types/lib/ecosystems/cppIncludeResolver.d.ts.map +1 -0
  140. package/types/lib/ecosystems/denoutils.d.ts +9 -3
  141. package/types/lib/ecosystems/denoutils.d.ts.map +1 -1
  142. package/types/lib/ecosystems/ecosystems.d.ts +62 -13
  143. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  144. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  145. package/types/lib/ecosystems/gradleutils.d.ts +50 -0
  146. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  147. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  148. package/types/lib/ecosystems/kosi.d.ts.map +1 -1
  149. package/types/lib/ecosystems/npmutils.d.ts +15 -0
  150. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  151. package/types/lib/ecosystems/parsers-dotnet.d.ts +118 -4
  152. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  153. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -1
  154. package/types/lib/ecosystems/parsers-gleam.d.ts.map +1 -1
  155. package/types/lib/ecosystems/parsers-go.d.ts +44 -2
  156. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  157. package/types/lib/ecosystems/parsers-js.d.ts +6 -1
  158. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  159. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -1
  160. package/types/lib/ecosystems/parsers-jvm.d.ts +46 -1
  161. package/types/lib/ecosystems/parsers-jvm.d.ts.map +1 -1
  162. package/types/lib/ecosystems/parsers-misc.d.ts +3 -1
  163. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  164. package/types/lib/ecosystems/parsers-python.d.ts +53 -3
  165. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  166. package/types/lib/ecosystems/parsers-terraform.d.ts +38 -21
  167. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -1
  168. package/types/lib/ecosystems/pythonutils.d.ts +27 -2
  169. package/types/lib/ecosystems/pythonutils.d.ts.map +1 -1
  170. package/types/lib/ecosystems/remote/huggingface.d.ts.map +1 -1
  171. package/types/lib/ecosystems/rubyutils.d.ts +21 -1
  172. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  173. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  174. package/types/lib/ecosystems/sbtutils.d.ts +88 -2
  175. package/types/lib/ecosystems/sbtutils.d.ts.map +1 -1
  176. package/types/lib/ecosystems/scalacliutils.d.ts +56 -0
  177. package/types/lib/ecosystems/scalacliutils.d.ts.map +1 -0
  178. package/types/lib/ecosystems/scalasem.d.ts +311 -0
  179. package/types/lib/ecosystems/scalasem.d.ts.map +1 -0
  180. package/types/lib/ecosystems/terraformRegistry.d.ts +9 -0
  181. package/types/lib/ecosystems/terraformRegistry.d.ts.map +1 -0
  182. package/types/lib/ecosystems/utils.d.ts +2 -2
  183. package/types/lib/ecosystems/utils.d.ts.map +1 -1
  184. package/types/lib/ecosystems/vendoredCode.d.ts +32 -0
  185. package/types/lib/ecosystems/vendoredCode.d.ts.map +1 -0
  186. package/types/lib/evinser/evinser.d.ts +75 -8
  187. package/types/lib/evinser/evinser.d.ts.map +1 -1
  188. package/types/lib/helpers/bomSigner.d.ts +80 -4
  189. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  190. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  191. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  192. package/types/lib/inventory/atomUtils.d.ts +82 -10
  193. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  194. package/types/lib/inventory/auditCategories.d.ts +3 -0
  195. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  196. package/types/lib/inventory/buildToolRateLimit.d.ts +38 -0
  197. package/types/lib/inventory/buildToolRateLimit.d.ts.map +1 -0
  198. package/types/lib/inventory/cacheCommands.d.ts +2 -1
  199. package/types/lib/inventory/cacheCommands.d.ts.map +1 -1
  200. package/types/lib/inventory/cmakeBuildDirs.d.ts +58 -0
  201. package/types/lib/inventory/cmakeBuildDirs.d.ts.map +1 -0
  202. package/types/lib/inventory/deps.d.ts +59 -1
  203. package/types/lib/inventory/deps.d.ts.map +1 -1
  204. package/types/lib/inventory/dosai.d.ts +57 -8
  205. package/types/lib/inventory/dosai.d.ts.map +1 -1
  206. package/types/lib/inventory/dosaiParsers.d.ts +53 -7
  207. package/types/lib/inventory/dosaiParsers.d.ts.map +1 -1
  208. package/types/lib/inventory/dynamic.d.ts +10 -0
  209. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  210. package/types/lib/inventory/evidenceUtils.d.ts +19 -4
  211. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  212. package/types/lib/inventory/fetchBatch.d.ts +83 -14
  213. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  214. package/types/lib/inventory/fetchDiskCache.d.ts +169 -0
  215. package/types/lib/inventory/fetchDiskCache.d.ts.map +1 -0
  216. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  217. package/types/lib/inventory/jvmLocalRepos.d.ts +178 -0
  218. package/types/lib/inventory/jvmLocalRepos.d.ts.map +1 -0
  219. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  220. package/types/lib/inventory/parentSelection.d.ts +34 -0
  221. package/types/lib/inventory/parentSelection.d.ts.map +1 -0
  222. package/types/lib/inventory/rustFormulationParser.d.ts.map +1 -1
  223. package/types/lib/inventory/scalaCoords.d.ts +80 -0
  224. package/types/lib/inventory/scalaCoords.d.ts.map +1 -0
  225. package/types/lib/inventory/source.d.ts.map +1 -1
  226. package/types/lib/inventory/spdx.d.ts +9 -0
  227. package/types/lib/inventory/spdx.d.ts.map +1 -1
  228. package/types/lib/inventory/traceRunner.d.ts +12 -0
  229. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  230. package/types/lib/inventory/tracedCrypto.d.ts +42 -0
  231. package/types/lib/inventory/tracedCrypto.d.ts.map +1 -0
  232. package/types/lib/managers/docker.d.ts.map +1 -1
  233. package/types/lib/managers/oci.d.ts +3 -1
  234. package/types/lib/managers/oci.d.ts.map +1 -1
  235. package/types/lib/parsers/cmakeCache.d.ts +16 -0
  236. package/types/lib/parsers/cmakeCache.d.ts.map +1 -1
  237. package/types/lib/parsers/cmakeLists.d.ts +2 -1
  238. package/types/lib/parsers/cmakeLists.d.ts.map +1 -1
  239. package/types/lib/parsers/cmakePresets.d.ts +78 -0
  240. package/types/lib/parsers/cmakePresets.d.ts.map +1 -0
  241. package/types/lib/parsers/compileCommands.d.ts +115 -0
  242. package/types/lib/parsers/compileCommands.d.ts.map +1 -0
  243. package/types/lib/parsers/strictJson.d.ts +46 -0
  244. package/types/lib/parsers/strictJson.d.ts.map +1 -0
  245. package/types/lib/parsers/terraformConfig.d.ts +70 -0
  246. package/types/lib/parsers/terraformConfig.d.ts.map +1 -0
  247. package/types/lib/parsers/terraformSource.d.ts +66 -0
  248. package/types/lib/parsers/terraformSource.d.ts.map +1 -0
  249. package/types/lib/server/server.d.ts.map +1 -1
  250. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  251. package/types/lib/stages/postgen/specVersionCompat.d.ts.map +1 -1
  252. package/types/lib/validator/index.d.ts +8 -0
  253. package/types/lib/validator/index.d.ts.map +1 -1
  254. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  255. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +0 -462
@@ -19,17 +19,133 @@ 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
+
33
149
  /**
34
150
  * Add the symbols a file uses to a component's `internal:ImportedSymbols`,
35
151
  * keeping every other property and the symbols already recorded.
@@ -54,6 +170,54 @@ function mergeImportedSymbols(apkg, symbols) {
54
170
  }
55
171
  }
56
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
+
57
221
  /**
58
222
  * Method to find c/c++ modules by collecting usages with atom
59
223
  *
@@ -61,8 +225,18 @@ function mergeImportedSymbols(apkg, symbols) {
61
225
  * @param {object} options Command line options
62
226
  * @param {array} osPkgsList Array of OS pacakges represented as components
63
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
64
232
  */
65
- export function getCppModules(src, options, osPkgsList, epkgList) {
233
+ export function getCppModules(
234
+ src,
235
+ options,
236
+ osPkgsList,
237
+ epkgList,
238
+ isFirstPartyHeader = undefined,
239
+ ) {
66
240
  // Generic is the type to use where the package registry could not be located
67
241
  const pkgType = "generic";
68
242
  const pkgList = [];
@@ -78,6 +252,15 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
78
252
  (epkgList || []).forEach((p) => {
79
253
  epkgMap[epkgKey(p.group, p.name)] = p;
80
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();
81
264
  // Let's look for any vcpkg.json file to tell us about the directory we're scanning
82
265
  // users can use this file to give us a clue even if they do not use vcpkg library manager
83
266
  if (safeExistsSync(join(src, "vcpkg.json"))) {
@@ -137,17 +320,19 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
137
320
  !epkgMap[epkgKey("", avcpkgName.toLowerCase())] &&
138
321
  !epkgMap[epkgKey("", avcpkgName.toUpperCase())]
139
322
  ) {
323
+ // the version vcpkg installed, when the build tree has the port
324
+ const installed = vcpkgPorts.get(avcpkgName.toLowerCase());
140
325
  const pkgPurl = build({
141
326
  type: pkgType,
142
327
  namespace: "" || null,
143
328
  name: avcpkgName,
144
- version: "" || null,
329
+ version: installed?.version || null,
145
330
  });
146
331
  const apkg = {
147
332
  group: "",
148
333
  name: avcpkgName,
149
334
  type: pkgType,
150
- version: "",
335
+ version: installed?.version || "",
151
336
  purl: pkgPurl,
152
337
  scope,
153
338
  "bom-ref": decodeURIComponent(pkgPurl),
@@ -156,6 +341,9 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
156
341
  ...(vcpkgFeatures
157
342
  ? [{ name: "cdx:vcpkg:features", value: vcpkgFeatures }]
158
343
  : []),
344
+ ...(installed
345
+ ? [{ name: "cdx:vcpkg:triplet", value: installed.triplet }]
346
+ : []),
159
347
  ],
160
348
  evidence: {
161
349
  identity: {
@@ -222,7 +410,7 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
222
410
  if (DEBUG_MODE) {
223
411
  console.log("Re-using existing slices file", options.usagesSlicesFile);
224
412
  }
225
- } else {
413
+ } else if (hasCppSources(src, options)) {
226
414
  sliceData = findAppModules(
227
415
  src,
228
416
  options.deep ? "c" : "h",
@@ -230,13 +418,125 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
230
418
  options.usagesSlicesFile,
231
419
  options,
232
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 = [];
233
426
  }
234
427
  const usageData = parseCUsageSlice(sliceData);
428
+ const includeInfo = parseCIncludeSlices(sliceData);
235
429
  const osComponents = new Map();
236
430
  const addedRefs = new Set();
237
- for (let afile of Object.keys(usageData)) {
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
+ )) {
238
538
  // Normalize windows separator
239
- afile = afile.replace("..\\", "").replace(/\\/g, "/");
539
+ const afile = sliceKey.replace("..\\", "").replace(/\\/g, "/");
240
540
  const fileName = basename(afile);
241
541
  if (!fileName?.length) {
242
542
  continue;
@@ -264,11 +564,38 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
264
564
  if (CPP_STD_MODULES.includes(name)) {
265
565
  continue;
266
566
  }
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
+ }
267
591
  // The OS package list is shared by every header: a component taken from it
268
592
  // is a copy, so the internal:PkgProvides the next header is matched against
269
593
  // stays intact. A component the caller already listed is enriched in place
270
594
  // and not listed again.
271
595
  const osPkg = getOSPackageForFile(afile, osPkgsList);
596
+ if (!osPkg && C_SYSTEM_HEADERS.has(afile)) {
597
+ continue;
598
+ }
272
599
  const listedPkg = osPkg ? undefined : epkgMap[epkgKey(group, name)];
273
600
  let apkg;
274
601
  if (osPkg) {
@@ -326,21 +653,9 @@ export function getCppModules(src, options, osPkgsList, epkgList) {
326
653
  };
327
654
  apkg["bom-ref"] = decodeURIComponent(apkg["purl"]);
328
655
  }
329
- if (usageData[afile]) {
330
- const usymbols = Array.from(usageData[afile])
331
- .filter(
332
- (v) =>
333
- !v.startsWith("<") &&
334
- !v.startsWith("__") &&
335
- v !== "main" &&
336
- !v.includes("anonymous_") &&
337
- !v.includes(afile),
338
- )
339
- .map((v) => v.split(":")[0])
340
- .sort();
341
- if (usymbols.length) {
342
- mergeImportedSymbols(apkg, usymbols);
343
- }
656
+ const usymbols = symbolsOf(sliceKey, afile);
657
+ if (usymbols.length) {
658
+ mergeImportedSymbols(apkg, usymbols);
344
659
  }
345
660
  // At this point, we have a package but we don't know what it's called
346
661
  // So let's try to locate this generic package using some heuristics