frida 16.2.1 → 16.2.2

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 (386) hide show
  1. package/BSDmakefile +6 -0
  2. package/Makefile +16 -0
  3. package/README.md +14 -11
  4. package/configure +18 -0
  5. package/configure.bat +22 -0
  6. package/dist/native.js +0 -8
  7. package/lib/application.ts +98 -0
  8. package/lib/authentication.ts +3 -0
  9. package/lib/build.py +50 -0
  10. package/lib/bus.ts +30 -0
  11. package/lib/cancellable.ts +33 -0
  12. package/lib/child.ts +15 -0
  13. package/lib/crash.ts +11 -0
  14. package/lib/device.ts +329 -0
  15. package/lib/device_manager.ts +69 -0
  16. package/lib/endpoint_parameters.ts +56 -0
  17. package/lib/icon.ts +15 -0
  18. package/lib/index.ts +311 -0
  19. package/lib/iostream.ts +78 -0
  20. package/lib/meson.build +53 -0
  21. package/lib/native.ts +9 -0
  22. package/lib/portal_membership.ts +10 -0
  23. package/lib/portal_service.ts +105 -0
  24. package/lib/process.ts +57 -0
  25. package/lib/relay.ts +44 -0
  26. package/lib/script.ts +352 -0
  27. package/lib/session.ts +113 -0
  28. package/lib/signals.ts +45 -0
  29. package/lib/socket_address.ts +35 -0
  30. package/lib/spawn.ts +4 -0
  31. package/lib/system_parameters.ts +78 -0
  32. package/make.bat +23 -0
  33. package/meson.build +160 -0
  34. package/meson.options +11 -0
  35. package/package.json +27 -6
  36. package/releng/deps.py +1133 -0
  37. package/releng/deps.toml +391 -0
  38. package/releng/devkit-assets/frida-core-example-unix.c +188 -0
  39. package/releng/devkit-assets/frida-core-example-windows.c +197 -0
  40. package/releng/devkit-assets/frida-core-example.sln +28 -0
  41. package/releng/devkit-assets/frida-core-example.vcxproj +157 -0
  42. package/releng/devkit-assets/frida-core-example.vcxproj.filters +27 -0
  43. package/releng/devkit-assets/frida-gum-example-unix.c +122 -0
  44. package/releng/devkit-assets/frida-gum-example-windows.c +132 -0
  45. package/releng/devkit-assets/frida-gum-example.sln +28 -0
  46. package/releng/devkit-assets/frida-gum-example.vcxproj +157 -0
  47. package/releng/devkit-assets/frida-gum-example.vcxproj.filters +27 -0
  48. package/releng/devkit-assets/frida-gumjs-example-unix.c +84 -0
  49. package/releng/devkit-assets/frida-gumjs-example-windows.c +91 -0
  50. package/releng/devkit-assets/frida-gumjs-example.sln +28 -0
  51. package/releng/devkit-assets/frida-gumjs-example.vcxproj +157 -0
  52. package/releng/devkit-assets/frida-gumjs-example.vcxproj.filters +27 -0
  53. package/releng/devkit.py +535 -0
  54. package/releng/env.py +420 -0
  55. package/releng/env_android.py +150 -0
  56. package/releng/env_apple.py +176 -0
  57. package/releng/env_generic.py +373 -0
  58. package/releng/frida_version.py +69 -0
  59. package/releng/machine_file.py +44 -0
  60. package/releng/machine_spec.py +290 -0
  61. package/releng/meson/meson.py +27 -0
  62. package/releng/meson/mesonbuild/__init__.py +0 -0
  63. package/releng/meson/mesonbuild/_pathlib.py +63 -0
  64. package/releng/meson/mesonbuild/_typing.py +69 -0
  65. package/releng/meson/mesonbuild/arglist.py +321 -0
  66. package/releng/meson/mesonbuild/ast/__init__.py +23 -0
  67. package/releng/meson/mesonbuild/ast/interpreter.py +441 -0
  68. package/releng/meson/mesonbuild/ast/introspection.py +374 -0
  69. package/releng/meson/mesonbuild/ast/postprocess.py +109 -0
  70. package/releng/meson/mesonbuild/ast/printer.py +620 -0
  71. package/releng/meson/mesonbuild/ast/visitor.py +161 -0
  72. package/releng/meson/mesonbuild/backend/__init__.py +0 -0
  73. package/releng/meson/mesonbuild/backend/backends.py +2047 -0
  74. package/releng/meson/mesonbuild/backend/ninjabackend.py +3808 -0
  75. package/releng/meson/mesonbuild/backend/nonebackend.py +26 -0
  76. package/releng/meson/mesonbuild/backend/vs2010backend.py +2078 -0
  77. package/releng/meson/mesonbuild/backend/vs2012backend.py +35 -0
  78. package/releng/meson/mesonbuild/backend/vs2013backend.py +34 -0
  79. package/releng/meson/mesonbuild/backend/vs2015backend.py +35 -0
  80. package/releng/meson/mesonbuild/backend/vs2017backend.py +59 -0
  81. package/releng/meson/mesonbuild/backend/vs2019backend.py +54 -0
  82. package/releng/meson/mesonbuild/backend/vs2022backend.py +54 -0
  83. package/releng/meson/mesonbuild/backend/xcodebackend.py +1781 -0
  84. package/releng/meson/mesonbuild/build.py +3249 -0
  85. package/releng/meson/mesonbuild/cargo/__init__.py +5 -0
  86. package/releng/meson/mesonbuild/cargo/builder.py +238 -0
  87. package/releng/meson/mesonbuild/cargo/cfg.py +274 -0
  88. package/releng/meson/mesonbuild/cargo/interpreter.py +733 -0
  89. package/releng/meson/mesonbuild/cargo/manifest.py +227 -0
  90. package/releng/meson/mesonbuild/cargo/version.py +95 -0
  91. package/releng/meson/mesonbuild/cmake/__init__.py +28 -0
  92. package/releng/meson/mesonbuild/cmake/common.py +331 -0
  93. package/releng/meson/mesonbuild/cmake/data/__init__.py +0 -0
  94. package/releng/meson/mesonbuild/cmake/data/preload.cmake +82 -0
  95. package/releng/meson/mesonbuild/cmake/executor.py +241 -0
  96. package/releng/meson/mesonbuild/cmake/fileapi.py +324 -0
  97. package/releng/meson/mesonbuild/cmake/generator.py +186 -0
  98. package/releng/meson/mesonbuild/cmake/interpreter.py +1267 -0
  99. package/releng/meson/mesonbuild/cmake/toolchain.py +248 -0
  100. package/releng/meson/mesonbuild/cmake/traceparser.py +814 -0
  101. package/releng/meson/mesonbuild/cmake/tracetargets.py +161 -0
  102. package/releng/meson/mesonbuild/compilers/__init__.py +86 -0
  103. package/releng/meson/mesonbuild/compilers/asm.py +307 -0
  104. package/releng/meson/mesonbuild/compilers/c.py +788 -0
  105. package/releng/meson/mesonbuild/compilers/c_function_attributes.py +143 -0
  106. package/releng/meson/mesonbuild/compilers/compilers.py +1388 -0
  107. package/releng/meson/mesonbuild/compilers/cpp.py +1035 -0
  108. package/releng/meson/mesonbuild/compilers/cs.py +136 -0
  109. package/releng/meson/mesonbuild/compilers/cuda.py +806 -0
  110. package/releng/meson/mesonbuild/compilers/cython.py +91 -0
  111. package/releng/meson/mesonbuild/compilers/d.py +861 -0
  112. package/releng/meson/mesonbuild/compilers/detect.py +1396 -0
  113. package/releng/meson/mesonbuild/compilers/fortran.py +523 -0
  114. package/releng/meson/mesonbuild/compilers/java.py +113 -0
  115. package/releng/meson/mesonbuild/compilers/mixins/__init__.py +0 -0
  116. package/releng/meson/mesonbuild/compilers/mixins/arm.py +167 -0
  117. package/releng/meson/mesonbuild/compilers/mixins/ccrx.py +113 -0
  118. package/releng/meson/mesonbuild/compilers/mixins/clang.py +170 -0
  119. package/releng/meson/mesonbuild/compilers/mixins/clike.py +1330 -0
  120. package/releng/meson/mesonbuild/compilers/mixins/compcert.py +117 -0
  121. package/releng/meson/mesonbuild/compilers/mixins/elbrus.py +93 -0
  122. package/releng/meson/mesonbuild/compilers/mixins/emscripten.py +89 -0
  123. package/releng/meson/mesonbuild/compilers/mixins/gnu.py +629 -0
  124. package/releng/meson/mesonbuild/compilers/mixins/intel.py +167 -0
  125. package/releng/meson/mesonbuild/compilers/mixins/islinker.py +120 -0
  126. package/releng/meson/mesonbuild/compilers/mixins/metrowerks.py +279 -0
  127. package/releng/meson/mesonbuild/compilers/mixins/pgi.py +88 -0
  128. package/releng/meson/mesonbuild/compilers/mixins/ti.py +130 -0
  129. package/releng/meson/mesonbuild/compilers/mixins/visualstudio.py +458 -0
  130. package/releng/meson/mesonbuild/compilers/mixins/xc16.py +111 -0
  131. package/releng/meson/mesonbuild/compilers/objc.py +120 -0
  132. package/releng/meson/mesonbuild/compilers/objcpp.py +102 -0
  133. package/releng/meson/mesonbuild/compilers/rust.py +230 -0
  134. package/releng/meson/mesonbuild/compilers/swift.py +131 -0
  135. package/releng/meson/mesonbuild/compilers/vala.py +121 -0
  136. package/releng/meson/mesonbuild/coredata.py +1532 -0
  137. package/releng/meson/mesonbuild/dependencies/__init__.py +252 -0
  138. package/releng/meson/mesonbuild/dependencies/base.py +663 -0
  139. package/releng/meson/mesonbuild/dependencies/boost.py +1083 -0
  140. package/releng/meson/mesonbuild/dependencies/cmake.py +656 -0
  141. package/releng/meson/mesonbuild/dependencies/coarrays.py +80 -0
  142. package/releng/meson/mesonbuild/dependencies/configtool.py +163 -0
  143. package/releng/meson/mesonbuild/dependencies/cuda.py +295 -0
  144. package/releng/meson/mesonbuild/dependencies/data/CMakeLists.txt +102 -0
  145. package/releng/meson/mesonbuild/dependencies/data/CMakeListsLLVM.txt +204 -0
  146. package/releng/meson/mesonbuild/dependencies/data/CMakePathInfo.txt +31 -0
  147. package/releng/meson/mesonbuild/dependencies/data/__init__.py +0 -0
  148. package/releng/meson/mesonbuild/dependencies/detect.py +225 -0
  149. package/releng/meson/mesonbuild/dependencies/dev.py +707 -0
  150. package/releng/meson/mesonbuild/dependencies/dub.py +424 -0
  151. package/releng/meson/mesonbuild/dependencies/factory.py +146 -0
  152. package/releng/meson/mesonbuild/dependencies/framework.py +111 -0
  153. package/releng/meson/mesonbuild/dependencies/hdf5.py +168 -0
  154. package/releng/meson/mesonbuild/dependencies/misc.py +618 -0
  155. package/releng/meson/mesonbuild/dependencies/mpi.py +231 -0
  156. package/releng/meson/mesonbuild/dependencies/pkgconfig.py +570 -0
  157. package/releng/meson/mesonbuild/dependencies/platform.py +52 -0
  158. package/releng/meson/mesonbuild/dependencies/python.py +431 -0
  159. package/releng/meson/mesonbuild/dependencies/qt.py +484 -0
  160. package/releng/meson/mesonbuild/dependencies/scalapack.py +142 -0
  161. package/releng/meson/mesonbuild/dependencies/ui.py +281 -0
  162. package/releng/meson/mesonbuild/depfile.py +82 -0
  163. package/releng/meson/mesonbuild/envconfig.py +480 -0
  164. package/releng/meson/mesonbuild/environment.py +987 -0
  165. package/releng/meson/mesonbuild/interpreter/__init__.py +47 -0
  166. package/releng/meson/mesonbuild/interpreter/compiler.py +900 -0
  167. package/releng/meson/mesonbuild/interpreter/dependencyfallbacks.py +386 -0
  168. package/releng/meson/mesonbuild/interpreter/interpreter.py +3595 -0
  169. package/releng/meson/mesonbuild/interpreter/interpreterobjects.py +1096 -0
  170. package/releng/meson/mesonbuild/interpreter/kwargs.py +479 -0
  171. package/releng/meson/mesonbuild/interpreter/mesonmain.py +487 -0
  172. package/releng/meson/mesonbuild/interpreter/primitives/__init__.py +29 -0
  173. package/releng/meson/mesonbuild/interpreter/primitives/array.py +108 -0
  174. package/releng/meson/mesonbuild/interpreter/primitives/boolean.py +52 -0
  175. package/releng/meson/mesonbuild/interpreter/primitives/dict.py +88 -0
  176. package/releng/meson/mesonbuild/interpreter/primitives/integer.py +86 -0
  177. package/releng/meson/mesonbuild/interpreter/primitives/range.py +38 -0
  178. package/releng/meson/mesonbuild/interpreter/primitives/string.py +247 -0
  179. package/releng/meson/mesonbuild/interpreter/type_checking.py +853 -0
  180. package/releng/meson/mesonbuild/interpreterbase/__init__.py +126 -0
  181. package/releng/meson/mesonbuild/interpreterbase/_unholder.py +25 -0
  182. package/releng/meson/mesonbuild/interpreterbase/baseobjects.py +174 -0
  183. package/releng/meson/mesonbuild/interpreterbase/decorators.py +806 -0
  184. package/releng/meson/mesonbuild/interpreterbase/disabler.py +35 -0
  185. package/releng/meson/mesonbuild/interpreterbase/exceptions.py +22 -0
  186. package/releng/meson/mesonbuild/interpreterbase/helpers.py +67 -0
  187. package/releng/meson/mesonbuild/interpreterbase/interpreterbase.py +665 -0
  188. package/releng/meson/mesonbuild/interpreterbase/operator.py +32 -0
  189. package/releng/meson/mesonbuild/linkers/__init__.py +20 -0
  190. package/releng/meson/mesonbuild/linkers/base.py +39 -0
  191. package/releng/meson/mesonbuild/linkers/detect.py +229 -0
  192. package/releng/meson/mesonbuild/linkers/linkers.py +1614 -0
  193. package/releng/meson/mesonbuild/mcompile.py +380 -0
  194. package/releng/meson/mesonbuild/mconf.py +368 -0
  195. package/releng/meson/mesonbuild/mdevenv.py +234 -0
  196. package/releng/meson/mesonbuild/mdist.py +376 -0
  197. package/releng/meson/mesonbuild/mesondata.py +38 -0
  198. package/releng/meson/mesonbuild/mesonlib.py +23 -0
  199. package/releng/meson/mesonbuild/mesonmain.py +289 -0
  200. package/releng/meson/mesonbuild/minit.py +204 -0
  201. package/releng/meson/mesonbuild/minstall.py +864 -0
  202. package/releng/meson/mesonbuild/mintro.py +667 -0
  203. package/releng/meson/mesonbuild/mlog.py +542 -0
  204. package/releng/meson/mesonbuild/modules/__init__.py +270 -0
  205. package/releng/meson/mesonbuild/modules/cmake.py +442 -0
  206. package/releng/meson/mesonbuild/modules/cuda.py +377 -0
  207. package/releng/meson/mesonbuild/modules/dlang.py +117 -0
  208. package/releng/meson/mesonbuild/modules/external_project.py +306 -0
  209. package/releng/meson/mesonbuild/modules/fs.py +323 -0
  210. package/releng/meson/mesonbuild/modules/gnome.py +2215 -0
  211. package/releng/meson/mesonbuild/modules/hotdoc.py +487 -0
  212. package/releng/meson/mesonbuild/modules/i18n.py +405 -0
  213. package/releng/meson/mesonbuild/modules/icestorm.py +123 -0
  214. package/releng/meson/mesonbuild/modules/java.py +112 -0
  215. package/releng/meson/mesonbuild/modules/keyval.py +65 -0
  216. package/releng/meson/mesonbuild/modules/modtest.py +33 -0
  217. package/releng/meson/mesonbuild/modules/pkgconfig.py +744 -0
  218. package/releng/meson/mesonbuild/modules/python.py +556 -0
  219. package/releng/meson/mesonbuild/modules/python3.py +85 -0
  220. package/releng/meson/mesonbuild/modules/qt.py +621 -0
  221. package/releng/meson/mesonbuild/modules/qt4.py +23 -0
  222. package/releng/meson/mesonbuild/modules/qt5.py +23 -0
  223. package/releng/meson/mesonbuild/modules/qt6.py +22 -0
  224. package/releng/meson/mesonbuild/modules/rust.py +355 -0
  225. package/releng/meson/mesonbuild/modules/simd.py +114 -0
  226. package/releng/meson/mesonbuild/modules/sourceset.py +291 -0
  227. package/releng/meson/mesonbuild/modules/wayland.py +151 -0
  228. package/releng/meson/mesonbuild/modules/windows.py +207 -0
  229. package/releng/meson/mesonbuild/mparser.py +1114 -0
  230. package/releng/meson/mesonbuild/msetup.py +365 -0
  231. package/releng/meson/mesonbuild/msubprojects.py +764 -0
  232. package/releng/meson/mesonbuild/mtest.py +2201 -0
  233. package/releng/meson/mesonbuild/munstable_coredata.py +107 -0
  234. package/releng/meson/mesonbuild/optinterpreter.py +276 -0
  235. package/releng/meson/mesonbuild/programs.py +367 -0
  236. package/releng/meson/mesonbuild/rewriter.py +1075 -0
  237. package/releng/meson/mesonbuild/scripts/__init__.py +10 -0
  238. package/releng/meson/mesonbuild/scripts/clangformat.py +55 -0
  239. package/releng/meson/mesonbuild/scripts/clangtidy.py +30 -0
  240. package/releng/meson/mesonbuild/scripts/cleantrees.py +35 -0
  241. package/releng/meson/mesonbuild/scripts/cmake_run_ctgt.py +103 -0
  242. package/releng/meson/mesonbuild/scripts/cmd_or_ps.ps1 +17 -0
  243. package/releng/meson/mesonbuild/scripts/copy.py +19 -0
  244. package/releng/meson/mesonbuild/scripts/coverage.py +214 -0
  245. package/releng/meson/mesonbuild/scripts/delwithsuffix.py +27 -0
  246. package/releng/meson/mesonbuild/scripts/depfixer.py +495 -0
  247. package/releng/meson/mesonbuild/scripts/depscan.py +198 -0
  248. package/releng/meson/mesonbuild/scripts/dirchanger.py +20 -0
  249. package/releng/meson/mesonbuild/scripts/env2mfile.py +402 -0
  250. package/releng/meson/mesonbuild/scripts/externalproject.py +106 -0
  251. package/releng/meson/mesonbuild/scripts/gettext.py +86 -0
  252. package/releng/meson/mesonbuild/scripts/gtkdochelper.py +286 -0
  253. package/releng/meson/mesonbuild/scripts/hotdochelper.py +40 -0
  254. package/releng/meson/mesonbuild/scripts/itstool.py +77 -0
  255. package/releng/meson/mesonbuild/scripts/meson_exe.py +115 -0
  256. package/releng/meson/mesonbuild/scripts/msgfmthelper.py +29 -0
  257. package/releng/meson/mesonbuild/scripts/pycompile.py +54 -0
  258. package/releng/meson/mesonbuild/scripts/python_info.py +121 -0
  259. package/releng/meson/mesonbuild/scripts/regen_checker.py +55 -0
  260. package/releng/meson/mesonbuild/scripts/run_tool.py +58 -0
  261. package/releng/meson/mesonbuild/scripts/scanbuild.py +57 -0
  262. package/releng/meson/mesonbuild/scripts/symbolextractor.py +322 -0
  263. package/releng/meson/mesonbuild/scripts/tags.py +44 -0
  264. package/releng/meson/mesonbuild/scripts/test_loaded_modules.py +14 -0
  265. package/releng/meson/mesonbuild/scripts/uninstall.py +41 -0
  266. package/releng/meson/mesonbuild/scripts/vcstagger.py +35 -0
  267. package/releng/meson/mesonbuild/scripts/yasm.py +24 -0
  268. package/releng/meson/mesonbuild/templates/__init__.py +0 -0
  269. package/releng/meson/mesonbuild/templates/cpptemplates.py +143 -0
  270. package/releng/meson/mesonbuild/templates/cstemplates.py +90 -0
  271. package/releng/meson/mesonbuild/templates/ctemplates.py +126 -0
  272. package/releng/meson/mesonbuild/templates/cudatemplates.py +143 -0
  273. package/releng/meson/mesonbuild/templates/dlangtemplates.py +109 -0
  274. package/releng/meson/mesonbuild/templates/fortrantemplates.py +101 -0
  275. package/releng/meson/mesonbuild/templates/javatemplates.py +94 -0
  276. package/releng/meson/mesonbuild/templates/mesontemplates.py +70 -0
  277. package/releng/meson/mesonbuild/templates/objcpptemplates.py +126 -0
  278. package/releng/meson/mesonbuild/templates/objctemplates.py +126 -0
  279. package/releng/meson/mesonbuild/templates/rusttemplates.py +79 -0
  280. package/releng/meson/mesonbuild/templates/samplefactory.py +41 -0
  281. package/releng/meson/mesonbuild/templates/sampleimpl.py +160 -0
  282. package/releng/meson/mesonbuild/templates/valatemplates.py +82 -0
  283. package/releng/meson/mesonbuild/utils/__init__.py +0 -0
  284. package/releng/meson/mesonbuild/utils/core.py +166 -0
  285. package/releng/meson/mesonbuild/utils/platform.py +27 -0
  286. package/releng/meson/mesonbuild/utils/posix.py +32 -0
  287. package/releng/meson/mesonbuild/utils/universal.py +2445 -0
  288. package/releng/meson/mesonbuild/utils/vsenv.py +126 -0
  289. package/releng/meson/mesonbuild/utils/win32.py +29 -0
  290. package/releng/meson/mesonbuild/wrap/__init__.py +59 -0
  291. package/releng/meson/mesonbuild/wrap/wrap.py +846 -0
  292. package/releng/meson/mesonbuild/wrap/wraptool.py +198 -0
  293. package/releng/meson-scripts/BSDmakefile +6 -0
  294. package/releng/meson-scripts/Makefile +16 -0
  295. package/releng/meson-scripts/configure +18 -0
  296. package/releng/meson-scripts/configure.bat +22 -0
  297. package/releng/meson-scripts/make.bat +23 -0
  298. package/releng/meson_configure.py +506 -0
  299. package/releng/meson_make.py +131 -0
  300. package/releng/mkdevkit.py +107 -0
  301. package/releng/mkfatmacho.py +54 -0
  302. package/releng/post-process-oabi.py +97 -0
  303. package/releng/progress.py +14 -0
  304. package/releng/sync-from-upstream.py +185 -0
  305. package/releng/tomlkit/tomlkit/__init__.py +59 -0
  306. package/releng/tomlkit/tomlkit/_compat.py +22 -0
  307. package/releng/tomlkit/tomlkit/_types.py +83 -0
  308. package/releng/tomlkit/tomlkit/_utils.py +158 -0
  309. package/releng/tomlkit/tomlkit/api.py +308 -0
  310. package/releng/tomlkit/tomlkit/container.py +875 -0
  311. package/releng/tomlkit/tomlkit/exceptions.py +227 -0
  312. package/releng/tomlkit/tomlkit/items.py +1967 -0
  313. package/releng/tomlkit/tomlkit/parser.py +1141 -0
  314. package/releng/tomlkit/tomlkit/py.typed +0 -0
  315. package/releng/tomlkit/tomlkit/source.py +180 -0
  316. package/releng/tomlkit/tomlkit/toml_char.py +52 -0
  317. package/releng/tomlkit/tomlkit/toml_document.py +7 -0
  318. package/releng/tomlkit/tomlkit/toml_file.py +58 -0
  319. package/releng/winenv.py +140 -0
  320. package/scripts/adjust-version.py +19 -0
  321. package/scripts/detect-version.py +40 -0
  322. package/scripts/fetch-abi-bits.py +343 -0
  323. package/scripts/install.js +23 -0
  324. package/scripts/package.py +15 -0
  325. package/src/addon.cc +76 -0
  326. package/src/application.cc +148 -0
  327. package/src/application.h +31 -0
  328. package/src/authentication.cc +174 -0
  329. package/src/authentication.h +24 -0
  330. package/src/bus.cc +167 -0
  331. package/src/bus.h +33 -0
  332. package/src/cancellable.cc +117 -0
  333. package/src/cancellable.h +31 -0
  334. package/src/child.cc +150 -0
  335. package/src/child.h +32 -0
  336. package/src/crash.cc +122 -0
  337. package/src/crash.h +30 -0
  338. package/src/device.cc +1302 -0
  339. package/src/device.h +55 -0
  340. package/src/device_manager.cc +362 -0
  341. package/src/device_manager.h +35 -0
  342. package/src/endpoint_parameters.cc +171 -0
  343. package/src/endpoint_parameters.h +28 -0
  344. package/src/glib_context.cc +62 -0
  345. package/src/glib_context.h +29 -0
  346. package/src/glib_object.cc +25 -0
  347. package/src/glib_object.h +37 -0
  348. package/src/iostream.cc +247 -0
  349. package/src/iostream.h +30 -0
  350. package/src/meson.build +26 -0
  351. package/src/operation.h +94 -0
  352. package/src/portal_membership.cc +100 -0
  353. package/src/portal_membership.h +26 -0
  354. package/src/portal_service.cc +401 -0
  355. package/src/portal_service.h +40 -0
  356. package/src/process.cc +135 -0
  357. package/src/process.h +30 -0
  358. package/src/relay.cc +139 -0
  359. package/src/relay.h +31 -0
  360. package/src/runtime.cc +443 -0
  361. package/src/runtime.h +64 -0
  362. package/src/script.cc +301 -0
  363. package/src/script.h +36 -0
  364. package/src/session.cc +860 -0
  365. package/src/session.h +42 -0
  366. package/src/signals.cc +334 -0
  367. package/src/signals.h +47 -0
  368. package/src/spawn.cc +95 -0
  369. package/src/spawn.h +27 -0
  370. package/src/usage_monitor.h +117 -0
  371. package/src/uv_context.cc +118 -0
  372. package/src/uv_context.h +40 -0
  373. package/src/win_delay_load_hook.cc +63 -0
  374. package/subprojects/frida-core.wrap +8 -0
  375. package/subprojects/nan.wrap +9 -0
  376. package/subprojects/packagefiles/nan.patch +13 -0
  377. package/test/data/index.ts +13 -0
  378. package/test/data/unixvictim-linux-x86 +0 -0
  379. package/test/data/unixvictim-linux-x86_64 +0 -0
  380. package/test/data/unixvictim-macos +0 -0
  381. package/test/device.ts +27 -0
  382. package/test/device_manager.ts +16 -0
  383. package/test/labrat.ts +32 -0
  384. package/test/script.ts +176 -0
  385. package/test/session.ts +73 -0
  386. package/tsconfig.json +18 -0
@@ -0,0 +1,1267 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2019 The Meson development team
3
+
4
+ # This class contains the basic functionality needed to run any interpreter
5
+ # or an interpreter-based tool.
6
+ from __future__ import annotations
7
+
8
+ from functools import lru_cache
9
+ from os import environ
10
+ from pathlib import Path
11
+ import re
12
+ import typing as T
13
+
14
+ from .common import CMakeException, CMakeTarget, language_map, cmake_get_generator_args, check_cmake_args
15
+ from .fileapi import CMakeFileAPI
16
+ from .executor import CMakeExecutor
17
+ from .toolchain import CMakeToolchain, CMakeExecScope
18
+ from .traceparser import CMakeTraceParser
19
+ from .tracetargets import resolve_cmake_trace_targets
20
+ from .. import mlog, mesonlib
21
+ from ..mesonlib import MachineChoice, OrderedSet, path_is_in_root, relative_to_if_possible, OptionKey
22
+ from ..mesondata import DataFile
23
+ from ..compilers.compilers import assembler_suffixes, lang_suffixes, header_suffixes, obj_suffixes, lib_suffixes, is_header
24
+ from ..programs import ExternalProgram
25
+ from ..coredata import FORBIDDEN_TARGET_NAMES
26
+ from ..mparser import (
27
+ Token,
28
+ BaseNode,
29
+ CodeBlockNode,
30
+ FunctionNode,
31
+ ArrayNode,
32
+ ArgumentNode,
33
+ AssignmentNode,
34
+ BooleanNode,
35
+ StringNode,
36
+ IdNode,
37
+ IndexNode,
38
+ MethodNode,
39
+ NumberNode,
40
+ SymbolNode,
41
+ )
42
+
43
+
44
+ if T.TYPE_CHECKING:
45
+ from .common import CMakeConfiguration, TargetOptions
46
+ from .traceparser import CMakeGeneratorTarget
47
+ from .._typing import ImmutableListProtocol
48
+ from ..backend.backends import Backend
49
+ from ..environment import Environment
50
+
51
+ TYPE_mixed = T.Union[str, int, bool, Path, BaseNode]
52
+ TYPE_mixed_list = T.Union[TYPE_mixed, T.Sequence[TYPE_mixed]]
53
+ TYPE_mixed_kwargs = T.Dict[str, TYPE_mixed_list]
54
+
55
+ # Disable all warnings automatically enabled with --trace and friends
56
+ # See https://cmake.org/cmake/help/latest/variable/CMAKE_POLICY_WARNING_CMPNNNN.html
57
+ disable_policy_warnings = [
58
+ 'CMP0025',
59
+ 'CMP0047',
60
+ 'CMP0056',
61
+ 'CMP0060',
62
+ 'CMP0065',
63
+ 'CMP0066',
64
+ 'CMP0067',
65
+ 'CMP0082',
66
+ 'CMP0089',
67
+ 'CMP0102',
68
+ ]
69
+
70
+ target_type_map = {
71
+ 'STATIC_LIBRARY': 'static_library',
72
+ 'MODULE_LIBRARY': 'shared_module',
73
+ 'SHARED_LIBRARY': 'shared_library',
74
+ 'EXECUTABLE': 'executable',
75
+ 'OBJECT_LIBRARY': 'static_library',
76
+ 'INTERFACE_LIBRARY': 'header_only'
77
+ }
78
+
79
+ skip_targets = ['UTILITY']
80
+
81
+ blacklist_compiler_flags = [
82
+ '-Wall', '-Wextra', '-Weverything', '-Werror', '-Wpedantic', '-pedantic', '-w',
83
+ '/W1', '/W2', '/W3', '/W4', '/Wall', '/WX', '/w',
84
+ '/O1', '/O2', '/Ob', '/Od', '/Og', '/Oi', '/Os', '/Ot', '/Ox', '/Oy', '/Ob0',
85
+ '/RTC1', '/RTCc', '/RTCs', '/RTCu',
86
+ '/Z7', '/Zi', '/ZI',
87
+ ]
88
+
89
+ blacklist_link_flags = [
90
+ '/machine:x64', '/machine:x86', '/machine:arm', '/machine:ebc',
91
+ '/debug', '/debug:fastlink', '/debug:full', '/debug:none',
92
+ '/incremental',
93
+ ]
94
+
95
+ blacklist_clang_cl_link_flags = ['/GR', '/EHsc', '/MDd', '/Zi', '/RTC1']
96
+
97
+ blacklist_link_libs = [
98
+ 'kernel32.lib',
99
+ 'user32.lib',
100
+ 'gdi32.lib',
101
+ 'winspool.lib',
102
+ 'shell32.lib',
103
+ 'ole32.lib',
104
+ 'oleaut32.lib',
105
+ 'uuid.lib',
106
+ 'comdlg32.lib',
107
+ 'advapi32.lib'
108
+ ]
109
+
110
+ transfer_dependencies_from = ['header_only']
111
+
112
+ _cmake_name_regex = re.compile(r'[^_a-zA-Z0-9]')
113
+ def _sanitize_cmake_name(name: str) -> str:
114
+ name = _cmake_name_regex.sub('_', name)
115
+ if name in FORBIDDEN_TARGET_NAMES or name.startswith('meson'):
116
+ name = 'cm_' + name
117
+ return name
118
+
119
+ class OutputTargetMap:
120
+ rm_so_version = re.compile(r'(\.[0-9]+)+$')
121
+
122
+ def __init__(self, build_dir: Path):
123
+ self.tgt_map: T.Dict[str, T.Union['ConverterTarget', 'ConverterCustomTarget']] = {}
124
+ self.build_dir = build_dir
125
+
126
+ def add(self, tgt: T.Union['ConverterTarget', 'ConverterCustomTarget']) -> None:
127
+ def assign_keys(keys: T.List[str]) -> None:
128
+ for i in [x for x in keys if x]:
129
+ self.tgt_map[i] = tgt
130
+ keys = [self._target_key(tgt.cmake_name)]
131
+ if isinstance(tgt, ConverterTarget):
132
+ keys += [tgt.full_name]
133
+ keys += [self._rel_artifact_key(x) for x in tgt.artifacts]
134
+ keys += [self._base_artifact_key(x) for x in tgt.artifacts]
135
+ if isinstance(tgt, ConverterCustomTarget):
136
+ keys += [self._rel_generated_file_key(x) for x in tgt.original_outputs]
137
+ keys += [self._base_generated_file_key(x) for x in tgt.original_outputs]
138
+ assign_keys(keys)
139
+
140
+ def _return_first_valid_key(self, keys: T.List[str]) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
141
+ for i in keys:
142
+ if i and i in self.tgt_map:
143
+ return self.tgt_map[i]
144
+ return None
145
+
146
+ def target(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
147
+ return self._return_first_valid_key([self._target_key(name)])
148
+
149
+ def executable(self, name: str) -> T.Optional['ConverterTarget']:
150
+ tgt = self.target(name)
151
+ if tgt is None or not isinstance(tgt, ConverterTarget):
152
+ return None
153
+ if tgt.meson_func() != 'executable':
154
+ return None
155
+ return tgt
156
+
157
+ def artifact(self, name: str) -> T.Optional[T.Union['ConverterTarget', 'ConverterCustomTarget']]:
158
+ keys = []
159
+ candidates = [name, OutputTargetMap.rm_so_version.sub('', name)]
160
+ for i in lib_suffixes:
161
+ if not name.endswith('.' + i):
162
+ continue
163
+ new_name = name[:-len(i) - 1]
164
+ new_name = OutputTargetMap.rm_so_version.sub('', new_name)
165
+ candidates += [f'{new_name}.{i}']
166
+ for i in candidates:
167
+ keys += [self._rel_artifact_key(Path(i)), Path(i).name, self._base_artifact_key(Path(i))]
168
+ return self._return_first_valid_key(keys)
169
+
170
+ def generated(self, name: Path) -> T.Optional['ConverterCustomTarget']:
171
+ res = self._return_first_valid_key([self._rel_generated_file_key(name), self._base_generated_file_key(name)])
172
+ assert res is None or isinstance(res, ConverterCustomTarget)
173
+ return res
174
+
175
+ # Utility functions to generate local keys
176
+ def _rel_path(self, fname: Path) -> T.Optional[Path]:
177
+ try:
178
+ return fname.resolve().relative_to(self.build_dir)
179
+ except ValueError:
180
+ pass
181
+ return None
182
+
183
+ def _target_key(self, tgt_name: str) -> str:
184
+ return f'__tgt_{tgt_name}__'
185
+
186
+ def _rel_generated_file_key(self, fname: Path) -> T.Optional[str]:
187
+ path = self._rel_path(fname)
188
+ return f'__relgen_{path.as_posix()}__' if path else None
189
+
190
+ def _base_generated_file_key(self, fname: Path) -> str:
191
+ return f'__gen_{fname.name}__'
192
+
193
+ def _rel_artifact_key(self, fname: Path) -> T.Optional[str]:
194
+ path = self._rel_path(fname)
195
+ return f'__relart_{path.as_posix()}__' if path else None
196
+
197
+ def _base_artifact_key(self, fname: Path) -> str:
198
+ return f'__art_{fname.name}__'
199
+
200
+ class ConverterTarget:
201
+ def __init__(self, target: CMakeTarget, env: 'Environment', for_machine: MachineChoice) -> None:
202
+ self.env = env
203
+ self.for_machine = for_machine
204
+ self.artifacts = target.artifacts
205
+ self.src_dir = target.src_dir
206
+ self.build_dir = target.build_dir
207
+ self.name = target.name
208
+ self.cmake_name = target.name
209
+ self.full_name = target.full_name
210
+ self.type = target.type
211
+ self.install = target.install
212
+ self.install_dir: T.Optional[Path] = None
213
+ self.link_libraries = target.link_libraries
214
+ self.link_flags = target.link_flags + target.link_lang_flags
215
+ self.depends_raw: T.List[str] = []
216
+ self.depends: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] = []
217
+
218
+ if target.install_paths:
219
+ self.install_dir = target.install_paths[0]
220
+
221
+ self.languages: T.Set[str] = set()
222
+ self.sources: T.List[Path] = []
223
+ self.generated: T.List[Path] = []
224
+ self.generated_ctgt: T.List[CustomTargetReference] = []
225
+ self.includes: T.List[Path] = []
226
+ self.sys_includes: T.List[Path] = []
227
+ self.link_with: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] = []
228
+ self.object_libs: T.List[ConverterTarget] = []
229
+ self.compile_opts: T.Dict[str, T.List[str]] = {}
230
+ self.public_compile_opts: T.List[str] = []
231
+ self.pie = False
232
+
233
+ # Project default override options (c_std, cpp_std, etc.)
234
+ self.override_options: T.List[str] = []
235
+
236
+ # Convert the target name to a valid meson target name
237
+ self.name = _sanitize_cmake_name(self.name)
238
+
239
+ self.generated_raw: T.List[Path] = []
240
+
241
+ for i in target.files:
242
+ languages: T.Set[str] = set()
243
+ src_suffixes: T.Set[str] = set()
244
+
245
+ # Insert suffixes
246
+ for j in i.sources:
247
+ if not j.suffix:
248
+ continue
249
+ src_suffixes.add(j.suffix[1:])
250
+
251
+ # Determine the meson language(s)
252
+ # Extract the default language from the explicit CMake field
253
+ lang_cmake_to_meson = {val.lower(): key for key, val in language_map.items()}
254
+ languages.add(lang_cmake_to_meson.get(i.language.lower(), 'c'))
255
+
256
+ # Determine missing languages from the source suffixes
257
+ for sfx in src_suffixes:
258
+ for key, val in lang_suffixes.items():
259
+ if sfx in val:
260
+ languages.add(key)
261
+ break
262
+
263
+ # Register the new languages and initialize the compile opts array
264
+ for lang in languages:
265
+ self.languages.add(lang)
266
+ if lang not in self.compile_opts:
267
+ self.compile_opts[lang] = []
268
+
269
+ # Add arguments, but avoid duplicates
270
+ args = i.flags
271
+ args += [f'-D{x}' for x in i.defines]
272
+ for lang in languages:
273
+ self.compile_opts[lang] += [x for x in args if x not in self.compile_opts[lang]]
274
+
275
+ # Handle include directories
276
+ self.includes += [x.path for x in i.includes if x.path not in self.includes and not x.isSystem]
277
+ self.sys_includes += [x.path for x in i.includes if x.path not in self.sys_includes and x.isSystem]
278
+
279
+ # Add sources to the right array
280
+ if i.is_generated:
281
+ self.generated_raw += i.sources
282
+ else:
283
+ self.sources += i.sources
284
+
285
+ def __repr__(self) -> str:
286
+ return f'<{self.__class__.__name__}: {self.name}>'
287
+
288
+ std_regex = re.compile(r'([-]{1,2}std=|/std:v?|[-]{1,2}std:)(.*)')
289
+
290
+ def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, subdir: Path, install_prefix: Path, trace: CMakeTraceParser) -> None:
291
+ # Detect setting the C and C++ standard and do additional compiler args manipulation
292
+ for i in ['c', 'cpp']:
293
+ if i not in self.compile_opts:
294
+ continue
295
+
296
+ temp: T.List[str] = []
297
+ for j in self.compile_opts[i]:
298
+ m = ConverterTarget.std_regex.match(j)
299
+ ctgt = output_target_map.generated(Path(j))
300
+ if m:
301
+ std = m.group(2)
302
+ supported = self._all_lang_stds(i)
303
+ if std not in supported:
304
+ mlog.warning(
305
+ 'Unknown {0}_std "{1}" -> Ignoring. Try setting the project-'
306
+ 'level {0}_std if build errors occur. Known '
307
+ '{0}_stds are: {2}'.format(i, std, ' '.join(supported)),
308
+ once=True
309
+ )
310
+ continue
311
+ self.override_options += [f'{i}_std={std}']
312
+ elif j in {'-fPIC', '-fpic', '-fPIE', '-fpie'}:
313
+ self.pie = True
314
+ elif isinstance(ctgt, ConverterCustomTarget):
315
+ # Sometimes projects pass generated source files as compiler
316
+ # flags. Add these as generated sources to ensure that the
317
+ # corresponding custom target is run.2
318
+ self.generated_raw += [Path(j)]
319
+ temp += [j]
320
+ elif j in blacklist_compiler_flags:
321
+ pass
322
+ else:
323
+ temp += [j]
324
+
325
+ self.compile_opts[i] = temp
326
+
327
+ # Make sure to force enable -fPIC for OBJECT libraries
328
+ if self.type.upper() == 'OBJECT_LIBRARY':
329
+ self.pie = True
330
+
331
+ # Use the CMake trace, if required
332
+ tgt = trace.targets.get(self.cmake_name)
333
+ if tgt:
334
+ self.depends_raw = trace.targets[self.cmake_name].depends
335
+
336
+ rtgt = resolve_cmake_trace_targets(self.cmake_name, trace, self.env)
337
+ self.includes += [Path(x) for x in rtgt.include_directories]
338
+ self.link_flags += rtgt.link_flags
339
+ self.public_compile_opts += rtgt.public_compile_opts
340
+ self.link_libraries += rtgt.libraries
341
+
342
+ elif self.type.upper() not in ['EXECUTABLE', 'OBJECT_LIBRARY']:
343
+ mlog.warning('CMake: Target', mlog.bold(self.cmake_name), 'not found in CMake trace. This can lead to build errors')
344
+
345
+ temp = []
346
+ for i in self.link_libraries:
347
+ # Let meson handle this arcane magic
348
+ if ',-rpath,' in i:
349
+ continue
350
+ if not Path(i).is_absolute():
351
+ link_with = output_target_map.artifact(i)
352
+ if link_with:
353
+ self.link_with += [link_with]
354
+ continue
355
+
356
+ temp += [i]
357
+ self.link_libraries = temp
358
+
359
+ # Filter out files that are not supported by the language
360
+ supported = list(assembler_suffixes) + list(header_suffixes) + list(obj_suffixes)
361
+ for i in self.languages:
362
+ supported += list(lang_suffixes[i])
363
+ supported = [f'.{x}' for x in supported]
364
+ self.sources = [x for x in self.sources if any(x.name.endswith(y) for y in supported)]
365
+ # Don't filter unsupported files from generated_raw because they
366
+ # can be GENERATED dependencies for other targets.
367
+ # See: https://github.com/mesonbuild/meson/issues/11607
368
+ # However, the dummy CMake rule files for Visual Studio still
369
+ # need to be filtered out. They don't exist (because the project was
370
+ # not generated at this time) but the fileapi will still
371
+ # report them on Windows.
372
+ # See: https://stackoverflow.com/a/41816323
373
+ self.generated_raw = [x for x in self.generated_raw if not x.name.endswith('.rule')]
374
+
375
+ # Make paths relative
376
+ def rel_path(x: Path, is_header: bool, is_generated: bool) -> T.Optional[Path]:
377
+ if not x.is_absolute():
378
+ x = self.src_dir / x
379
+ x = x.resolve()
380
+ assert x.is_absolute()
381
+ if not x.exists() and not any(x.name.endswith(y) for y in obj_suffixes) and not is_generated:
382
+ if path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True):
383
+ x.mkdir(parents=True, exist_ok=True)
384
+ return x.relative_to(Path(self.env.get_build_dir()) / subdir)
385
+ else:
386
+ mlog.warning('CMake: path', mlog.bold(x.as_posix()), 'does not exist.')
387
+ mlog.warning(' --> Ignoring. This can lead to build errors.')
388
+ return None
389
+ if x in trace.explicit_headers:
390
+ return None
391
+ if (
392
+ path_is_in_root(x, Path(self.env.get_source_dir()))
393
+ and not (
394
+ path_is_in_root(x, root_src_dir) or
395
+ path_is_in_root(x, Path(self.env.get_build_dir()))
396
+ )
397
+ ):
398
+ mlog.warning('CMake: path', mlog.bold(x.as_posix()), 'is inside the root project but', mlog.bold('not'), 'inside the subproject.')
399
+ mlog.warning(' --> Ignoring. This can lead to build errors.')
400
+ return None
401
+ if path_is_in_root(x, Path(self.env.get_build_dir())) and is_header:
402
+ return x.relative_to(Path(self.env.get_build_dir()) / subdir)
403
+ if path_is_in_root(x, root_src_dir):
404
+ return x.relative_to(root_src_dir)
405
+ return x
406
+
407
+ build_dir_rel = self.build_dir.relative_to(Path(self.env.get_build_dir()) / subdir)
408
+ self.generated_raw = [rel_path(x, False, True) for x in self.generated_raw]
409
+ self.includes = list(OrderedSet([rel_path(x, True, False) for x in OrderedSet(self.includes)] + [build_dir_rel]))
410
+ self.sys_includes = list(OrderedSet([rel_path(x, True, False) for x in OrderedSet(self.sys_includes)]))
411
+ self.sources = [rel_path(x, False, False) for x in self.sources]
412
+
413
+ # Resolve custom targets
414
+ for gen_file in self.generated_raw:
415
+ ctgt = output_target_map.generated(gen_file)
416
+ if ctgt:
417
+ assert isinstance(ctgt, ConverterCustomTarget)
418
+ ref = ctgt.get_ref(gen_file)
419
+ assert isinstance(ref, CustomTargetReference) and ref.valid()
420
+ self.generated_ctgt += [ref]
421
+ elif gen_file is not None:
422
+ self.generated += [gen_file]
423
+
424
+ # Remove delete entries
425
+ self.includes = [x for x in self.includes if x is not None]
426
+ self.sys_includes = [x for x in self.sys_includes if x is not None]
427
+ self.sources = [x for x in self.sources if x is not None]
428
+
429
+ # Make sure '.' is always in the include directories
430
+ if Path('.') not in self.includes:
431
+ self.includes += [Path('.')]
432
+
433
+ # make install dir relative to the install prefix
434
+ if self.install_dir and self.install_dir.is_absolute():
435
+ if path_is_in_root(self.install_dir, install_prefix):
436
+ self.install_dir = self.install_dir.relative_to(install_prefix)
437
+
438
+ # Remove blacklisted options and libs
439
+ def check_flag(flag: str) -> bool:
440
+ if flag.lower() in blacklist_link_flags or flag in blacklist_compiler_flags + blacklist_clang_cl_link_flags:
441
+ return False
442
+ if flag.startswith('/D'):
443
+ return False
444
+ return True
445
+
446
+ self.link_libraries = [x for x in self.link_libraries if x.lower() not in blacklist_link_libs]
447
+ self.link_flags = [x for x in self.link_flags if check_flag(x)]
448
+
449
+ # Handle OSX frameworks
450
+ def handle_frameworks(flags: T.List[str]) -> T.List[str]:
451
+ res: T.List[str] = []
452
+ for i in flags:
453
+ p = Path(i)
454
+ if not p.exists() or not p.name.endswith('.framework'):
455
+ res += [i]
456
+ continue
457
+ res += ['-framework', p.stem]
458
+ return res
459
+
460
+ self.link_libraries = handle_frameworks(self.link_libraries)
461
+ self.link_flags = handle_frameworks(self.link_flags)
462
+
463
+ # Handle explicit CMake add_dependency() calls
464
+ for i in self.depends_raw:
465
+ dep_tgt = output_target_map.target(i)
466
+ if dep_tgt:
467
+ self.depends.append(dep_tgt)
468
+
469
+ def process_object_libs(self, obj_target_list: T.List['ConverterTarget'], linker_workaround: bool) -> None:
470
+ # Try to detect the object library(s) from the generated input sources
471
+ temp = [x for x in self.generated if any(x.name.endswith('.' + y) for y in obj_suffixes)]
472
+ stem = [x.stem for x in temp]
473
+ exts = self._all_source_suffixes()
474
+ # Temp now stores the source filenames of the object files
475
+ for i in obj_target_list:
476
+ source_files = [x.name for x in i.sources + i.generated]
477
+ for j in stem:
478
+ # On some platforms (specifically looking at you Windows with vs20xy backend) CMake does
479
+ # not produce object files with the format `foo.cpp.obj`, instead it skipps the language
480
+ # suffix and just produces object files like `foo.obj`. Thus we have to do our best to
481
+ # undo this step and guess the correct language suffix of the object file. This is done
482
+ # by trying all language suffixes meson knows and checking if one of them fits.
483
+ candidates = [j]
484
+ if not any(j.endswith('.' + x) for x in exts):
485
+ mlog.warning('Object files do not contain source file extensions, thus falling back to guessing them.', once=True)
486
+ candidates += [f'{j}.{x}' for x in exts]
487
+ if any(x in source_files for x in candidates):
488
+ if linker_workaround:
489
+ self._append_objlib_sources(i)
490
+ else:
491
+ self.includes += i.includes
492
+ self.includes = list(OrderedSet(self.includes))
493
+ self.object_libs += [i]
494
+ break
495
+
496
+ # Filter out object files from the sources
497
+ self.generated = [x for x in self.generated if not any(x.name.endswith('.' + y) for y in obj_suffixes)]
498
+
499
+ def _append_objlib_sources(self, tgt: 'ConverterTarget') -> None:
500
+ self.includes += tgt.includes
501
+ self.sources += tgt.sources
502
+ self.generated += tgt.generated
503
+ self.generated_ctgt += tgt.generated_ctgt
504
+ self.includes = list(OrderedSet(self.includes))
505
+ self.sources = list(OrderedSet(self.sources))
506
+ self.generated = list(OrderedSet(self.generated))
507
+ self.generated_ctgt = list(OrderedSet(self.generated_ctgt))
508
+
509
+ # Inherit compiler arguments since they may be required for building
510
+ for lang, opts in tgt.compile_opts.items():
511
+ if lang not in self.compile_opts:
512
+ self.compile_opts[lang] = []
513
+ self.compile_opts[lang] += [x for x in opts if x not in self.compile_opts[lang]]
514
+
515
+ @lru_cache(maxsize=None)
516
+ def _all_source_suffixes(self) -> 'ImmutableListProtocol[str]':
517
+ suffixes: T.List[str] = []
518
+ for exts in lang_suffixes.values():
519
+ suffixes.extend(exts)
520
+ return suffixes
521
+
522
+ @lru_cache(maxsize=None)
523
+ def _all_lang_stds(self, lang: str) -> 'ImmutableListProtocol[str]':
524
+ try:
525
+ res = self.env.coredata.options[OptionKey('std', machine=MachineChoice.BUILD, lang=lang)].choices
526
+ except KeyError:
527
+ return []
528
+
529
+ # TODO: Get rid of this once we have proper typing for options
530
+ assert isinstance(res, list)
531
+ for i in res:
532
+ assert isinstance(i, str)
533
+
534
+ return res
535
+
536
+ def process_inter_target_dependencies(self) -> None:
537
+ # Move the dependencies from all transfer_dependencies_from to the target
538
+ to_process = list(self.depends)
539
+ processed = []
540
+ new_deps = []
541
+ for i in to_process:
542
+ processed += [i]
543
+ if isinstance(i, ConverterTarget) and i.meson_func() in transfer_dependencies_from:
544
+ to_process += [x for x in i.depends if x not in processed]
545
+ else:
546
+ new_deps += [i]
547
+ self.depends = list(OrderedSet(new_deps))
548
+
549
+ def cleanup_dependencies(self) -> None:
550
+ # Clear the dependencies from targets that where moved from
551
+ if self.meson_func() in transfer_dependencies_from:
552
+ self.depends = []
553
+
554
+ def meson_func(self) -> str:
555
+ return target_type_map.get(self.type.upper())
556
+
557
+ def log(self) -> None:
558
+ mlog.log('Target', mlog.bold(self.name), f'({self.cmake_name})')
559
+ mlog.log(' -- artifacts: ', mlog.bold(str(self.artifacts)))
560
+ mlog.log(' -- full_name: ', mlog.bold(self.full_name))
561
+ mlog.log(' -- type: ', mlog.bold(self.type))
562
+ mlog.log(' -- install: ', mlog.bold('true' if self.install else 'false'))
563
+ mlog.log(' -- install_dir: ', mlog.bold(self.install_dir.as_posix() if self.install_dir else ''))
564
+ mlog.log(' -- link_libraries: ', mlog.bold(str(self.link_libraries)))
565
+ mlog.log(' -- link_with: ', mlog.bold(str(self.link_with)))
566
+ mlog.log(' -- object_libs: ', mlog.bold(str(self.object_libs)))
567
+ mlog.log(' -- link_flags: ', mlog.bold(str(self.link_flags)))
568
+ mlog.log(' -- languages: ', mlog.bold(str(self.languages)))
569
+ mlog.log(' -- includes: ', mlog.bold(str(self.includes)))
570
+ mlog.log(' -- sys_includes: ', mlog.bold(str(self.sys_includes)))
571
+ mlog.log(' -- sources: ', mlog.bold(str(self.sources)))
572
+ mlog.log(' -- generated: ', mlog.bold(str(self.generated)))
573
+ mlog.log(' -- generated_ctgt: ', mlog.bold(str(self.generated_ctgt)))
574
+ mlog.log(' -- pie: ', mlog.bold('true' if self.pie else 'false'))
575
+ mlog.log(' -- override_opts: ', mlog.bold(str(self.override_options)))
576
+ mlog.log(' -- depends: ', mlog.bold(str(self.depends)))
577
+ mlog.log(' -- options:')
578
+ for key, val in self.compile_opts.items():
579
+ mlog.log(' -', key, '=', mlog.bold(str(val)))
580
+
581
+ class CustomTargetReference:
582
+ def __init__(self, ctgt: 'ConverterCustomTarget', index: int) -> None:
583
+ self.ctgt = ctgt
584
+ self.index = index
585
+
586
+ def __repr__(self) -> str:
587
+ if self.valid():
588
+ return '<{}: {} [{}]>'.format(self.__class__.__name__, self.ctgt.name, self.ctgt.outputs[self.index])
589
+ else:
590
+ return f'<{self.__class__.__name__}: INVALID REFERENCE>'
591
+
592
+ def valid(self) -> bool:
593
+ return self.ctgt is not None and self.index >= 0
594
+
595
+ def filename(self) -> str:
596
+ return self.ctgt.outputs[self.index]
597
+
598
+ class ConverterCustomTarget:
599
+ tgt_counter = 0
600
+ out_counter = 0
601
+
602
+ def __init__(self, target: CMakeGeneratorTarget, env: 'Environment', for_machine: MachineChoice) -> None:
603
+ assert target.current_bin_dir is not None
604
+ assert target.current_src_dir is not None
605
+ self.name = target.name
606
+ if not self.name:
607
+ self.name = f'custom_tgt_{ConverterCustomTarget.tgt_counter}'
608
+ ConverterCustomTarget.tgt_counter += 1
609
+ self.cmake_name = str(self.name)
610
+ self.original_outputs = list(target.outputs)
611
+ self.outputs = [x.name for x in self.original_outputs]
612
+ self.conflict_map: T.Dict[str, str] = {}
613
+ self.command: T.List[T.List[T.Union[str, ConverterTarget]]] = []
614
+ self.working_dir = target.working_dir
615
+ self.depends_raw = target.depends
616
+ self.inputs: T.List[T.Union[str, CustomTargetReference]] = []
617
+ self.depends: T.List[T.Union[ConverterTarget, ConverterCustomTarget]] = []
618
+ self.current_bin_dir = target.current_bin_dir
619
+ self.current_src_dir = target.current_src_dir
620
+ self.env = env
621
+ self.for_machine = for_machine
622
+ self._raw_target = target
623
+
624
+ # Convert the target name to a valid meson target name
625
+ self.name = _sanitize_cmake_name(self.name)
626
+
627
+ def __repr__(self) -> str:
628
+ return f'<{self.__class__.__name__}: {self.name} {self.outputs}>'
629
+
630
+ def postprocess(self, output_target_map: OutputTargetMap, root_src_dir: Path, all_outputs: T.List[str], trace: CMakeTraceParser) -> None:
631
+ # Default the working directory to ${CMAKE_CURRENT_BINARY_DIR}
632
+ if self.working_dir is None:
633
+ self.working_dir = self.current_bin_dir
634
+
635
+ # relative paths in the working directory are always relative
636
+ # to ${CMAKE_CURRENT_BINARY_DIR}
637
+ if not self.working_dir.is_absolute():
638
+ self.working_dir = self.current_bin_dir / self.working_dir
639
+
640
+ # Modify the original outputs if they are relative. Again,
641
+ # relative paths are relative to ${CMAKE_CURRENT_BINARY_DIR}
642
+ def ensure_absolute(x: Path) -> Path:
643
+ if x.is_absolute():
644
+ return x
645
+ else:
646
+ return self.current_bin_dir / x
647
+ self.original_outputs = [ensure_absolute(x) for x in self.original_outputs]
648
+
649
+ # Ensure that there is no duplicate output in the project so
650
+ # that meson can handle cases where the same filename is
651
+ # generated in multiple directories
652
+ temp_outputs: T.List[str] = []
653
+ for i in self.outputs:
654
+ if i in all_outputs:
655
+ old = str(i)
656
+ i = f'c{ConverterCustomTarget.out_counter}_{i}'
657
+ ConverterCustomTarget.out_counter += 1
658
+ self.conflict_map[old] = i
659
+ all_outputs += [i]
660
+ temp_outputs += [i]
661
+ self.outputs = temp_outputs
662
+
663
+ # Check if the command is a build target
664
+ commands: T.List[T.List[T.Union[str, ConverterTarget]]] = []
665
+ for curr_cmd in self._raw_target.command:
666
+ assert isinstance(curr_cmd, list)
667
+ assert curr_cmd[0] != '', "An empty string is not a valid executable"
668
+ cmd: T.List[T.Union[str, ConverterTarget]] = []
669
+
670
+ for j in curr_cmd:
671
+ if not j:
672
+ continue
673
+ target = output_target_map.executable(j)
674
+ if target:
675
+ # When cross compiling, binaries have to be executed with an exe_wrapper (for instance wine for mingw-w64)
676
+ if self.env.exe_wrapper is not None and self.env.properties[self.for_machine].get_cmake_use_exe_wrapper():
677
+ assert isinstance(self.env.exe_wrapper, ExternalProgram)
678
+ cmd += self.env.exe_wrapper.get_command()
679
+ cmd += [target]
680
+ continue
681
+ elif j in trace.targets:
682
+ trace_tgt = trace.targets[j]
683
+ if trace_tgt.type == 'EXECUTABLE' and 'IMPORTED_LOCATION' in trace_tgt.properties:
684
+ cmd += trace_tgt.properties['IMPORTED_LOCATION']
685
+ continue
686
+ mlog.debug(f'CMake: Found invalid CMake target "{j}" --> ignoring \n{trace_tgt}')
687
+
688
+ # Fallthrough on error
689
+ cmd += [j]
690
+
691
+ commands += [cmd]
692
+ self.command = commands
693
+
694
+ # If the custom target does not declare any output, create a dummy
695
+ # one that can be used as dependency.
696
+ if not self.outputs:
697
+ self.outputs = [self.name + '.h']
698
+
699
+ # Check dependencies and input files
700
+ for i in self.depends_raw:
701
+ if not i:
702
+ continue
703
+ raw = Path(i)
704
+ art = output_target_map.artifact(i)
705
+ tgt = output_target_map.target(i)
706
+ gen = output_target_map.generated(raw)
707
+
708
+ rel_to_root = None
709
+ try:
710
+ rel_to_root = raw.relative_to(root_src_dir)
711
+ except ValueError:
712
+ rel_to_root = None
713
+
714
+ # First check for existing files. Only then check for existing
715
+ # targets, etc. This reduces the chance of misdetecting input files
716
+ # as outputs from other targets.
717
+ # See https://github.com/mesonbuild/meson/issues/6632
718
+ if not raw.is_absolute() and (self.current_src_dir / raw).is_file():
719
+ self.inputs += [(self.current_src_dir / raw).relative_to(root_src_dir).as_posix()]
720
+ elif raw.is_absolute() and raw.exists() and rel_to_root is not None:
721
+ self.inputs += [rel_to_root.as_posix()]
722
+ elif art:
723
+ self.depends += [art]
724
+ elif tgt:
725
+ self.depends += [tgt]
726
+ elif gen:
727
+ ctgt_ref = gen.get_ref(raw)
728
+ assert ctgt_ref is not None
729
+ self.inputs += [ctgt_ref]
730
+
731
+ def process_inter_target_dependencies(self) -> None:
732
+ # Move the dependencies from all transfer_dependencies_from to the target
733
+ to_process = list(self.depends)
734
+ processed = []
735
+ new_deps = []
736
+ for i in to_process:
737
+ processed += [i]
738
+ if isinstance(i, ConverterTarget) and i.meson_func() in transfer_dependencies_from:
739
+ to_process += [x for x in i.depends if x not in processed]
740
+ else:
741
+ new_deps += [i]
742
+ self.depends = list(OrderedSet(new_deps))
743
+
744
+ def get_ref(self, fname: Path) -> T.Optional[CustomTargetReference]:
745
+ name = fname.name
746
+ try:
747
+ if name in self.conflict_map:
748
+ name = self.conflict_map[name]
749
+ idx = self.outputs.index(name)
750
+ return CustomTargetReference(self, idx)
751
+ except ValueError:
752
+ return None
753
+
754
+ def log(self) -> None:
755
+ mlog.log('Custom Target', mlog.bold(self.name), f'({self.cmake_name})')
756
+ mlog.log(' -- command: ', mlog.bold(str(self.command)))
757
+ mlog.log(' -- outputs: ', mlog.bold(str(self.outputs)))
758
+ mlog.log(' -- conflict_map: ', mlog.bold(str(self.conflict_map)))
759
+ mlog.log(' -- working_dir: ', mlog.bold(str(self.working_dir)))
760
+ mlog.log(' -- depends_raw: ', mlog.bold(str(self.depends_raw)))
761
+ mlog.log(' -- inputs: ', mlog.bold(str(self.inputs)))
762
+ mlog.log(' -- depends: ', mlog.bold(str(self.depends)))
763
+
764
+ class CMakeInterpreter:
765
+ def __init__(self, subdir: Path, install_prefix: Path, env: 'Environment', backend: 'Backend', for_machine: MachineChoice):
766
+ self.subdir = subdir
767
+ self.src_dir = Path(env.get_source_dir(), subdir)
768
+ self.build_dir_rel = subdir / '__CMake_build'
769
+ self.build_dir = Path(env.get_build_dir()) / self.build_dir_rel
770
+ self.install_prefix = install_prefix
771
+ self.env = env
772
+ self.for_machine = for_machine
773
+ self.backend_name = backend.name
774
+ self.linkers: T.Set[str] = set()
775
+ self.fileapi = CMakeFileAPI(self.build_dir)
776
+
777
+ # Raw CMake results
778
+ self.bs_files: T.List[Path] = []
779
+ self.codemodel_configs: T.Optional[T.List[CMakeConfiguration]] = None
780
+ self.cmake_stderr: T.Optional[str] = None
781
+
782
+ # Analysed data
783
+ self.project_name = ''
784
+ self.project_version = ''
785
+ self.languages: T.List[str] = []
786
+ self.targets: T.List[ConverterTarget] = []
787
+ self.custom_targets: T.List[ConverterCustomTarget] = []
788
+ self.trace: CMakeTraceParser
789
+ self.output_target_map = OutputTargetMap(self.build_dir)
790
+
791
+ # Generated meson data
792
+ self.generated_targets: T.Dict[str, T.Dict[str, T.Optional[str]]] = {}
793
+ self.internal_name_map: T.Dict[str, str] = {}
794
+
795
+ # Do some special handling for object libraries for certain configurations
796
+ self._object_lib_workaround = False
797
+ if self.backend_name.startswith('vs'):
798
+ for comp in self.env.coredata.compilers[self.for_machine].values():
799
+ if comp.get_linker_id() == 'link':
800
+ self._object_lib_workaround = True
801
+ break
802
+
803
+ def configure(self, extra_cmake_options: T.List[str]) -> CMakeExecutor:
804
+ # Find CMake
805
+ cmake_exe = CMakeExecutor(self.env, '>=3.14', self.for_machine)
806
+ if not cmake_exe.found():
807
+ raise CMakeException('Unable to find CMake')
808
+ self.trace = CMakeTraceParser(cmake_exe.version(), self.build_dir, self.env, permissive=True)
809
+
810
+ preload_file = DataFile('cmake/data/preload.cmake').write_to_private(self.env)
811
+ toolchain = CMakeToolchain(cmake_exe, self.env, self.for_machine, CMakeExecScope.SUBPROJECT, self.build_dir, preload_file)
812
+ toolchain_file = toolchain.write()
813
+
814
+ # TODO: drop this check once the deprecated `cmake_args` kwarg is removed
815
+ extra_cmake_options = check_cmake_args(extra_cmake_options)
816
+
817
+ cmake_args = []
818
+ cmake_args += cmake_get_generator_args(self.env)
819
+ cmake_args += [f'-DCMAKE_INSTALL_PREFIX={self.install_prefix}']
820
+ cmake_args += extra_cmake_options
821
+ trace_args = self.trace.trace_args()
822
+ cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in disable_policy_warnings]
823
+
824
+ self.fileapi.setup_request()
825
+
826
+ # Run CMake
827
+ mlog.log()
828
+ with mlog.nested():
829
+ mlog.log('Configuring the build directory with', mlog.bold('CMake'), 'version', mlog.cyan(cmake_exe.version()))
830
+ mlog.log(mlog.bold('Running CMake with:'), ' '.join(cmake_args))
831
+ mlog.log(mlog.bold(' - build directory: '), self.build_dir.as_posix())
832
+ mlog.log(mlog.bold(' - source directory: '), self.src_dir.as_posix())
833
+ mlog.log(mlog.bold(' - toolchain file: '), toolchain_file.as_posix())
834
+ mlog.log(mlog.bold(' - preload file: '), preload_file.as_posix())
835
+ mlog.log(mlog.bold(' - trace args: '), ' '.join(trace_args))
836
+ mlog.log(mlog.bold(' - disabled policy warnings:'), '[{}]'.format(', '.join(disable_policy_warnings)))
837
+ mlog.log()
838
+ self.build_dir.mkdir(parents=True, exist_ok=True)
839
+ os_env = environ.copy()
840
+ os_env['LC_ALL'] = 'C'
841
+ final_args = cmake_args + trace_args + cmcmp_args + toolchain.get_cmake_args() + [self.src_dir.as_posix()]
842
+
843
+ cmake_exe.set_exec_mode(print_cmout=True, always_capture_stderr=self.trace.requires_stderr())
844
+ rc, _, self.cmake_stderr = cmake_exe.call(final_args, self.build_dir, env=os_env, disable_cache=True)
845
+
846
+ mlog.log()
847
+ h = mlog.green('SUCCEEDED') if rc == 0 else mlog.red('FAILED')
848
+ mlog.log('CMake configuration:', h)
849
+ if rc != 0:
850
+ # get the last CMake error - We only need the message function for this:
851
+ self.trace.functions = {'message': self.trace.functions['message']}
852
+ self.trace.parse(self.cmake_stderr)
853
+ error = f': {self.trace.errors[-1]}' if self.trace.errors else ''
854
+ raise CMakeException(f'Failed to configure the CMake subproject{error}')
855
+
856
+ return cmake_exe
857
+
858
+ def initialise(self, extra_cmake_options: T.List[str]) -> None:
859
+ # Configure the CMake project to generate the file API data
860
+ self.configure(extra_cmake_options)
861
+
862
+ # Parse the result
863
+ self.fileapi.load_reply()
864
+
865
+ # Load the buildsystem file list
866
+ cmake_files = self.fileapi.get_cmake_sources()
867
+ self.bs_files = [x.file for x in cmake_files if not x.is_cmake and not x.is_temp]
868
+ self.bs_files = [relative_to_if_possible(x, Path(self.env.get_source_dir())) for x in self.bs_files]
869
+ self.bs_files = [x for x in self.bs_files if not path_is_in_root(x, Path(self.env.get_build_dir()), resolve=True)]
870
+ self.bs_files = list(OrderedSet(self.bs_files))
871
+
872
+ # Load the codemodel configurations
873
+ self.codemodel_configs = self.fileapi.get_cmake_configurations()
874
+
875
+ self.project_version = self.fileapi.get_project_version()
876
+
877
+ def analyse(self) -> None:
878
+ if self.codemodel_configs is None:
879
+ raise CMakeException('CMakeInterpreter was not initialized')
880
+
881
+ # Clear analyser data
882
+ self.project_name = ''
883
+ self.languages = []
884
+ self.targets = []
885
+ self.custom_targets = []
886
+
887
+ # Parse the trace
888
+ self.trace.parse(self.cmake_stderr)
889
+
890
+ # Find all targets
891
+ added_target_names: T.List[str] = []
892
+ for i_0 in self.codemodel_configs:
893
+ for j_0 in i_0.projects:
894
+ if not self.project_name:
895
+ self.project_name = j_0.name
896
+ for k_0 in j_0.targets:
897
+ # Avoid duplicate targets from different configurations and known
898
+ # dummy CMake internal target types
899
+ if k_0.type not in skip_targets and k_0.name not in added_target_names:
900
+ added_target_names += [k_0.name]
901
+ self.targets += [ConverterTarget(k_0, self.env, self.for_machine)]
902
+
903
+ # Add interface targets from trace, if not already present.
904
+ # This step is required because interface targets were removed from
905
+ # the CMake file API output.
906
+ api_target_name_list = [x.name for x in self.targets]
907
+ for i_1 in self.trace.targets.values():
908
+ if i_1.type != 'INTERFACE' or i_1.name in api_target_name_list or i_1.imported:
909
+ continue
910
+ dummy = CMakeTarget({
911
+ 'name': i_1.name,
912
+ 'type': 'INTERFACE_LIBRARY',
913
+ 'sourceDirectory': self.src_dir,
914
+ 'buildDirectory': self.build_dir,
915
+ })
916
+ self.targets += [ConverterTarget(dummy, self.env, self.for_machine)]
917
+
918
+ for i_2 in self.trace.custom_targets:
919
+ self.custom_targets += [ConverterCustomTarget(i_2, self.env, self.for_machine)]
920
+
921
+ # generate the output_target_map
922
+ for i_3 in [*self.targets, *self.custom_targets]:
923
+ assert isinstance(i_3, (ConverterTarget, ConverterCustomTarget))
924
+ self.output_target_map.add(i_3)
925
+
926
+ # First pass: Basic target cleanup
927
+ object_libs = []
928
+ custom_target_outputs: T.List[str] = []
929
+ for ctgt in self.custom_targets:
930
+ ctgt.postprocess(self.output_target_map, self.src_dir, custom_target_outputs, self.trace)
931
+ for tgt in self.targets:
932
+ tgt.postprocess(self.output_target_map, self.src_dir, self.subdir, self.install_prefix, self.trace)
933
+ if tgt.type == 'OBJECT_LIBRARY':
934
+ object_libs += [tgt]
935
+ self.languages += [x for x in tgt.languages if x not in self.languages]
936
+
937
+ # Second pass: Detect object library dependencies
938
+ for tgt in self.targets:
939
+ tgt.process_object_libs(object_libs, self._object_lib_workaround)
940
+
941
+ # Third pass: Reassign dependencies to avoid some loops
942
+ for tgt in self.targets:
943
+ tgt.process_inter_target_dependencies()
944
+ for ctgt in self.custom_targets:
945
+ ctgt.process_inter_target_dependencies()
946
+
947
+ # Fourth pass: Remove rassigned dependencies
948
+ for tgt in self.targets:
949
+ tgt.cleanup_dependencies()
950
+
951
+ mlog.log('CMake project', mlog.bold(self.project_name), mlog.bold(self.project_version), 'has', mlog.bold(str(len(self.targets) + len(self.custom_targets))), 'build targets.')
952
+
953
+ def pretend_to_be_meson(self, options: TargetOptions) -> CodeBlockNode:
954
+ if not self.project_name:
955
+ raise CMakeException('CMakeInterpreter was not analysed')
956
+
957
+ def token(tid: str = 'string', val: TYPE_mixed = '') -> Token:
958
+ return Token(tid, self.subdir.as_posix(), 0, 0, 0, None, val)
959
+
960
+ def symbol(val: str) -> SymbolNode:
961
+ return SymbolNode(token('', val))
962
+
963
+ def string(value: str) -> StringNode:
964
+ return StringNode(token(val=value), escape=False)
965
+
966
+ def id_node(value: str) -> IdNode:
967
+ return IdNode(token(val=value))
968
+
969
+ def number(value: int) -> NumberNode:
970
+ return NumberNode(token(val=str(value)))
971
+
972
+ def nodeify(value: TYPE_mixed_list) -> BaseNode:
973
+ if isinstance(value, str):
974
+ return string(value)
975
+ if isinstance(value, Path):
976
+ return string(value.as_posix())
977
+ elif isinstance(value, bool):
978
+ return BooleanNode(token(val=value))
979
+ elif isinstance(value, int):
980
+ return number(value)
981
+ elif isinstance(value, list):
982
+ return array(value)
983
+ elif isinstance(value, BaseNode):
984
+ return value
985
+ raise RuntimeError('invalid type of value: {} ({})'.format(type(value).__name__, str(value)))
986
+
987
+ def indexed(node: BaseNode, index: int) -> IndexNode:
988
+ return IndexNode(node, symbol('['), nodeify(index), symbol(']'))
989
+
990
+ def array(elements: TYPE_mixed_list) -> ArrayNode:
991
+ args = ArgumentNode(token())
992
+ if not isinstance(elements, list):
993
+ elements = [args]
994
+ args.arguments += [nodeify(x) for x in elements if x is not None]
995
+ return ArrayNode(symbol('['), args, symbol(']'))
996
+
997
+ def function(name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> FunctionNode:
998
+ args = [] if args is None else args
999
+ kwargs = {} if kwargs is None else kwargs
1000
+ args_n = ArgumentNode(token())
1001
+ if not isinstance(args, list):
1002
+ assert isinstance(args, (str, int, bool, Path, BaseNode))
1003
+ args = [args]
1004
+ args_n.arguments = [nodeify(x) for x in args if x is not None]
1005
+ args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None}
1006
+ func_n = FunctionNode(id_node(name), symbol('('), args_n, symbol(')'))
1007
+ return func_n
1008
+
1009
+ def method(obj: BaseNode, name: str, args: T.Optional[TYPE_mixed_list] = None, kwargs: T.Optional[TYPE_mixed_kwargs] = None) -> MethodNode:
1010
+ args = [] if args is None else args
1011
+ kwargs = {} if kwargs is None else kwargs
1012
+ args_n = ArgumentNode(token())
1013
+ if not isinstance(args, list):
1014
+ assert isinstance(args, (str, int, bool, Path, BaseNode))
1015
+ args = [args]
1016
+ args_n.arguments = [nodeify(x) for x in args if x is not None]
1017
+ args_n.kwargs = {id_node(k): nodeify(v) for k, v in kwargs.items() if v is not None}
1018
+ return MethodNode(obj, symbol('.'), id_node(name), symbol('('), args_n, symbol(')'))
1019
+
1020
+ def assign(var_name: str, value: BaseNode) -> AssignmentNode:
1021
+ return AssignmentNode(id_node(var_name), symbol('='), value)
1022
+
1023
+ # Generate the root code block and the project function call
1024
+ root_cb = CodeBlockNode(token())
1025
+ root_cb.lines += [function('project', [self.project_name] + self.languages, {'version': self.project_version} if self.project_version else None)]
1026
+
1027
+ # Add the run script for custom commands
1028
+
1029
+ # Add the targets
1030
+ processing: T.List[str] = []
1031
+ processed: T.Dict[str, T.Dict[str, T.Optional[str]]] = {}
1032
+ name_map: T.Dict[str, str] = {}
1033
+
1034
+ def extract_tgt(tgt: T.Union[ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> IdNode:
1035
+ tgt_name = None
1036
+ if isinstance(tgt, (ConverterTarget, ConverterCustomTarget)):
1037
+ tgt_name = tgt.name
1038
+ elif isinstance(tgt, CustomTargetReference):
1039
+ tgt_name = tgt.ctgt.name
1040
+ assert tgt_name is not None and tgt_name in processed
1041
+ res_var = processed[tgt_name]['tgt']
1042
+ return id_node(res_var) if res_var else None
1043
+
1044
+ def detect_cycle(tgt: T.Union[ConverterTarget, ConverterCustomTarget]) -> None:
1045
+ if tgt.name in processing:
1046
+ raise CMakeException('Cycle in CMake inputs/dependencies detected')
1047
+ processing.append(tgt.name)
1048
+
1049
+ def resolve_ctgt_ref(ref: CustomTargetReference) -> T.Union[IdNode, IndexNode]:
1050
+ tgt_var = extract_tgt(ref)
1051
+ if len(ref.ctgt.outputs) == 1:
1052
+ return tgt_var
1053
+ else:
1054
+ return indexed(tgt_var, ref.index)
1055
+
1056
+ def process_target(tgt: ConverterTarget) -> None:
1057
+ detect_cycle(tgt)
1058
+
1059
+ # First handle inter target dependencies
1060
+ link_with: T.List[IdNode] = []
1061
+ objec_libs: T.List[IdNode] = []
1062
+ sources: T.List[Path] = []
1063
+ generated: T.List[T.Union[IdNode, IndexNode]] = []
1064
+ generated_filenames: T.List[str] = []
1065
+ custom_targets: T.List[ConverterCustomTarget] = []
1066
+ dependencies: T.List[IdNode] = []
1067
+ for i in tgt.link_with:
1068
+ assert isinstance(i, ConverterTarget)
1069
+ if i.name not in processed:
1070
+ process_target(i)
1071
+ link_with += [extract_tgt(i)]
1072
+ for i in tgt.object_libs:
1073
+ assert isinstance(i, ConverterTarget)
1074
+ if i.name not in processed:
1075
+ process_target(i)
1076
+ objec_libs += [extract_tgt(i)]
1077
+ for i in tgt.depends:
1078
+ if not isinstance(i, ConverterCustomTarget):
1079
+ continue
1080
+ if i.name not in processed:
1081
+ process_custom_target(i)
1082
+ dependencies += [extract_tgt(i)]
1083
+
1084
+ # Generate the source list and handle generated sources
1085
+ sources += tgt.sources
1086
+ sources += tgt.generated
1087
+
1088
+ for ctgt_ref in tgt.generated_ctgt:
1089
+ ctgt = ctgt_ref.ctgt
1090
+ if ctgt.name not in processed:
1091
+ process_custom_target(ctgt)
1092
+ generated += [resolve_ctgt_ref(ctgt_ref)]
1093
+ generated_filenames += [ctgt_ref.filename()]
1094
+ if ctgt not in custom_targets:
1095
+ custom_targets += [ctgt]
1096
+
1097
+ # Add all header files from all used custom targets. This
1098
+ # ensures that all custom targets are built before any
1099
+ # sources of the current target are compiled and thus all
1100
+ # header files are present. This step is necessary because
1101
+ # CMake always ensures that a custom target is executed
1102
+ # before another target if at least one output is used.
1103
+ for ctgt in custom_targets:
1104
+ for j in ctgt.outputs:
1105
+ if not is_header(j) or j in generated_filenames:
1106
+ continue
1107
+
1108
+ generated += [resolve_ctgt_ref(ctgt.get_ref(Path(j)))]
1109
+ generated_filenames += [j]
1110
+
1111
+ # Determine the meson function to use for the build target
1112
+ tgt_func = tgt.meson_func()
1113
+ if not tgt_func:
1114
+ raise CMakeException(f'Unknown target type "{tgt.type}"')
1115
+
1116
+ # Determine the variable names
1117
+ inc_var = f'{tgt.name}_inc'
1118
+ dir_var = f'{tgt.name}_dir'
1119
+ sys_var = f'{tgt.name}_sys'
1120
+ src_var = f'{tgt.name}_src'
1121
+ dep_var = f'{tgt.name}_dep'
1122
+ tgt_var = tgt.name
1123
+
1124
+ install_tgt = options.get_install(tgt.cmake_name, tgt.install)
1125
+
1126
+ # Generate target kwargs
1127
+ tgt_kwargs: TYPE_mixed_kwargs = {
1128
+ 'build_by_default': install_tgt,
1129
+ 'link_args': options.get_link_args(tgt.cmake_name, tgt.link_flags + tgt.link_libraries),
1130
+ 'link_with': link_with,
1131
+ 'include_directories': id_node(inc_var),
1132
+ 'install': install_tgt,
1133
+ 'override_options': options.get_override_options(tgt.cmake_name, tgt.override_options),
1134
+ 'objects': [method(x, 'extract_all_objects') for x in objec_libs],
1135
+ }
1136
+
1137
+ # Only set if installed and only override if it is set
1138
+ if install_tgt and tgt.install_dir:
1139
+ tgt_kwargs['install_dir'] = tgt.install_dir
1140
+
1141
+ # Handle compiler args
1142
+ for key, val in tgt.compile_opts.items():
1143
+ tgt_kwargs[f'{key}_args'] = options.get_compile_args(tgt.cmake_name, key, val)
1144
+
1145
+ # Handle -fPCI, etc
1146
+ if tgt_func == 'executable':
1147
+ tgt_kwargs['pie'] = tgt.pie
1148
+ elif tgt_func == 'static_library':
1149
+ tgt_kwargs['pic'] = tgt.pie
1150
+
1151
+ # declare_dependency kwargs
1152
+ dep_kwargs: TYPE_mixed_kwargs = {
1153
+ 'link_args': tgt.link_flags + tgt.link_libraries,
1154
+ 'link_with': id_node(tgt_var),
1155
+ 'compile_args': tgt.public_compile_opts,
1156
+ 'include_directories': id_node(inc_var),
1157
+ }
1158
+
1159
+ if dependencies:
1160
+ generated += dependencies
1161
+
1162
+ # Generate the function nodes
1163
+ dir_node = assign(dir_var, function('include_directories', tgt.includes))
1164
+ sys_node = assign(sys_var, function('include_directories', tgt.sys_includes, {'is_system': True}))
1165
+ inc_node = assign(inc_var, array([id_node(dir_var), id_node(sys_var)]))
1166
+ node_list = [dir_node, sys_node, inc_node]
1167
+ if tgt_func == 'header_only':
1168
+ del dep_kwargs['link_with']
1169
+ dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
1170
+ node_list += [dep_node]
1171
+ src_var = None
1172
+ tgt_var = None
1173
+ else:
1174
+ src_node = assign(src_var, function('files', sources))
1175
+ tgt_node = assign(tgt_var, function(tgt_func, [tgt_var, id_node(src_var), *generated], tgt_kwargs))
1176
+ node_list += [src_node, tgt_node]
1177
+ if tgt_func in {'static_library', 'shared_library'}:
1178
+ dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
1179
+ node_list += [dep_node]
1180
+ elif tgt_func == 'shared_module':
1181
+ del dep_kwargs['link_with']
1182
+ dep_node = assign(dep_var, function('declare_dependency', kwargs=dep_kwargs))
1183
+ node_list += [dep_node]
1184
+ else:
1185
+ dep_var = None
1186
+
1187
+ # Add the nodes to the ast
1188
+ root_cb.lines += node_list
1189
+ processed[tgt.name] = {'inc': inc_var, 'src': src_var, 'dep': dep_var, 'tgt': tgt_var, 'func': tgt_func}
1190
+ name_map[tgt.cmake_name] = tgt.name
1191
+
1192
+ def process_custom_target(tgt: ConverterCustomTarget) -> None:
1193
+ # CMake allows to specify multiple commands in a custom target.
1194
+ # To map this to meson, a helper script is used to execute all
1195
+ # commands in order. This additionally allows setting the working
1196
+ # directory.
1197
+
1198
+ detect_cycle(tgt)
1199
+ tgt_var = tgt.name
1200
+
1201
+ def resolve_source(x: T.Union[str, ConverterTarget, ConverterCustomTarget, CustomTargetReference]) -> T.Union[str, IdNode, IndexNode]:
1202
+ if isinstance(x, ConverterTarget):
1203
+ if x.name not in processed:
1204
+ process_target(x)
1205
+ return extract_tgt(x)
1206
+ if isinstance(x, ConverterCustomTarget):
1207
+ if x.name not in processed:
1208
+ process_custom_target(x)
1209
+ return extract_tgt(x)
1210
+ elif isinstance(x, CustomTargetReference):
1211
+ if x.ctgt.name not in processed:
1212
+ process_custom_target(x.ctgt)
1213
+ return resolve_ctgt_ref(x)
1214
+ else:
1215
+ return x
1216
+
1217
+ # Generate the command list
1218
+ command: T.List[T.Union[str, IdNode, IndexNode]] = []
1219
+ command += mesonlib.get_meson_command()
1220
+ command += ['--internal', 'cmake_run_ctgt']
1221
+ command += ['-o', '@OUTPUT@']
1222
+ if tgt.original_outputs:
1223
+ command += ['-O'] + [x.as_posix() for x in tgt.original_outputs]
1224
+ command += ['-d', tgt.working_dir.as_posix()]
1225
+
1226
+ # Generate the commands. Subcommands are separated by ';;;'
1227
+ for cmd in tgt.command:
1228
+ command += [resolve_source(x) for x in cmd] + [';;;']
1229
+
1230
+ tgt_kwargs: TYPE_mixed_kwargs = {
1231
+ 'input': [resolve_source(x) for x in tgt.inputs],
1232
+ 'output': tgt.outputs,
1233
+ 'command': command,
1234
+ 'depends': [resolve_source(x) for x in tgt.depends],
1235
+ }
1236
+
1237
+ root_cb.lines += [assign(tgt_var, function('custom_target', [tgt.name], tgt_kwargs))]
1238
+ processed[tgt.name] = {'inc': None, 'src': None, 'dep': None, 'tgt': tgt_var, 'func': 'custom_target'}
1239
+ name_map[tgt.cmake_name] = tgt.name
1240
+
1241
+ # Now generate the target function calls
1242
+ for ctgt in self.custom_targets:
1243
+ if ctgt.name not in processed:
1244
+ process_custom_target(ctgt)
1245
+ for tgt in self.targets:
1246
+ if tgt.name not in processed:
1247
+ process_target(tgt)
1248
+
1249
+ self.generated_targets = processed
1250
+ self.internal_name_map = name_map
1251
+ return root_cb
1252
+
1253
+ def target_info(self, target: str) -> T.Optional[T.Dict[str, str]]:
1254
+ # Try resolving the target name
1255
+ # start by checking if there is a 100% match (excluding the name prefix)
1256
+ prx_tgt = _sanitize_cmake_name(target)
1257
+ if prx_tgt in self.generated_targets:
1258
+ return self.generated_targets[prx_tgt]
1259
+ # check if there exists a name mapping
1260
+ if target in self.internal_name_map:
1261
+ target = self.internal_name_map[target]
1262
+ assert target in self.generated_targets
1263
+ return self.generated_targets[target]
1264
+ return None
1265
+
1266
+ def target_list(self) -> T.List[str]:
1267
+ return list(self.internal_name_map.keys())