frida 16.2.0 → 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,1532 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2013-2024 The Meson development team
3
+ # Copyright © 2023-2024 Intel Corporation
4
+
5
+ from __future__ import annotations
6
+
7
+ import copy
8
+
9
+ from . import mlog, mparser
10
+ import pickle, os, uuid
11
+ import sys
12
+ from itertools import chain
13
+ from pathlib import PurePath
14
+ from collections import OrderedDict, abc
15
+ from dataclasses import dataclass
16
+
17
+ from .mesonlib import (
18
+ HoldableObject, MesonBugException,
19
+ MesonException, EnvironmentException, MachineChoice, PerMachine,
20
+ PerMachineDefaultable, default_libdir, default_libexecdir,
21
+ default_prefix, default_datadir, default_includedir, default_infodir,
22
+ default_localedir, default_mandir, default_sbindir, default_sysconfdir,
23
+ listify_array_value, OptionKey, OptionType, stringlistify,
24
+ pickle_load
25
+ )
26
+ from .wrap import WrapMode
27
+ import ast
28
+ import argparse
29
+ import configparser
30
+ import enum
31
+ import shlex
32
+ import typing as T
33
+
34
+ if T.TYPE_CHECKING:
35
+ from typing_extensions import Protocol
36
+
37
+ from . import dependencies
38
+ from .compilers.compilers import Compiler, CompileResult, RunResult, CompileCheckMode
39
+ from .dependencies.detect import TV_DepID
40
+ from .environment import Environment
41
+ from .mesonlib import FileOrString
42
+ from .cmake.traceparser import CMakeCacheEntry
43
+ from .interpreterbase import SubProject
44
+
45
+ class SharedCMDOptions(Protocol):
46
+
47
+ """Representation of command line options from Meson setup, configure,
48
+ and dist.
49
+
50
+ :param projectoptions: The raw list of command line options given
51
+ :param cmd_line_options: command line options parsed into an OptionKey:
52
+ str mapping
53
+ """
54
+
55
+ cmd_line_options: T.Dict[OptionKey, str]
56
+ projectoptions: T.List[str]
57
+ cross_file: T.List[str]
58
+ native_file: T.List[str]
59
+
60
+ OptionDictType = T.Union[T.Dict[str, 'UserOption[T.Any]'], 'OptionsView']
61
+ MutableKeyedOptionDictType = T.Dict['OptionKey', 'UserOption[T.Any]']
62
+ KeyedOptionDictType = T.Union[MutableKeyedOptionDictType, 'OptionsView']
63
+ CompilerCheckCacheKey = T.Tuple[T.Tuple[str, ...], str, FileOrString, T.Tuple[str, ...], CompileCheckMode]
64
+ # code, args
65
+ RunCheckCacheKey = T.Tuple[str, T.Tuple[str, ...]]
66
+
67
+ # typeshed
68
+ StrOrBytesPath = T.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]
69
+
70
+ # Check major_versions_differ() if changing versioning scheme.
71
+ #
72
+ # Pip requires that RCs are named like this: '0.1.0.rc1'
73
+ # But the corresponding Git tag needs to be '0.1.0rc1'
74
+ version = '1.4.99'
75
+
76
+ # The next stable version when we are in dev. This is used to allow projects to
77
+ # require meson version >=1.2.0 when using 1.1.99. FeatureNew won't warn when
78
+ # using a feature introduced in 1.2.0 when using Meson 1.1.99.
79
+ stable_version = version
80
+ if stable_version.endswith('.99'):
81
+ stable_version_array = stable_version.split('.')
82
+ stable_version_array[-1] = '0'
83
+ stable_version_array[-2] = str(int(stable_version_array[-2]) + 1)
84
+ stable_version = '.'.join(stable_version_array)
85
+
86
+ backendlist = ['ninja', 'vs', 'vs2010', 'vs2012', 'vs2013', 'vs2015', 'vs2017', 'vs2019', 'vs2022', 'xcode', 'none']
87
+ genvslitelist = ['vs2022']
88
+ buildtypelist = ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom']
89
+
90
+ DEFAULT_YIELDING = False
91
+
92
+ # Can't bind this near the class method it seems, sadly.
93
+ _T = T.TypeVar('_T')
94
+
95
+
96
+ def get_genvs_default_buildtype_list() -> list[str]:
97
+ # just debug, debugoptimized, and release for now
98
+ # but this should probably be configurable through some extra option, alongside --genvslite.
99
+ return buildtypelist[1:-2]
100
+
101
+
102
+ class MesonVersionMismatchException(MesonException):
103
+ '''Build directory generated with Meson version is incompatible with current version'''
104
+ def __init__(self, old_version: str, current_version: str, extra_msg: str = '') -> None:
105
+ super().__init__(f'Build directory has been generated with Meson version {old_version}, '
106
+ f'which is incompatible with the current version {current_version}.'
107
+ + extra_msg)
108
+ self.old_version = old_version
109
+ self.current_version = current_version
110
+
111
+
112
+ class UserOption(T.Generic[_T], HoldableObject):
113
+ def __init__(self, name: str, description: str, choices: T.Optional[T.Union[str, T.List[_T]]],
114
+ yielding: bool,
115
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
116
+ super().__init__()
117
+ self.name = name
118
+ self.choices = choices
119
+ self.description = description
120
+ if not isinstance(yielding, bool):
121
+ raise MesonException('Value of "yielding" must be a boolean.')
122
+ self.yielding = yielding
123
+ self.deprecated = deprecated
124
+ self.readonly = False
125
+
126
+ def listify(self, value: T.Any) -> T.List[T.Any]:
127
+ return [value]
128
+
129
+ def printable_value(self) -> T.Union[str, int, bool, T.List[T.Union[str, int, bool]]]:
130
+ assert isinstance(self.value, (str, int, bool, list))
131
+ return self.value
132
+
133
+ # Check that the input is a valid value and return the
134
+ # "cleaned" or "native" version. For example the Boolean
135
+ # option could take the string "true" and return True.
136
+ def validate_value(self, value: T.Any) -> _T:
137
+ raise RuntimeError('Derived option class did not override validate_value.')
138
+
139
+ def set_value(self, newvalue: T.Any) -> bool:
140
+ oldvalue = getattr(self, 'value', None)
141
+ self.value = self.validate_value(newvalue)
142
+ return self.value != oldvalue
143
+
144
+ class UserStringOption(UserOption[str]):
145
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
146
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
147
+ super().__init__(name, description, None, yielding, deprecated)
148
+ self.set_value(value)
149
+
150
+ def validate_value(self, value: T.Any) -> str:
151
+ if not isinstance(value, str):
152
+ raise MesonException(f'The value of option "{self.name}" is "{value}", which is not a string.')
153
+ return value
154
+
155
+ class UserBooleanOption(UserOption[bool]):
156
+ def __init__(self, name: str, description: str, value: bool, yielding: bool = DEFAULT_YIELDING,
157
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
158
+ super().__init__(name, description, [True, False], yielding, deprecated)
159
+ self.set_value(value)
160
+
161
+ def __bool__(self) -> bool:
162
+ return self.value
163
+
164
+ def validate_value(self, value: T.Any) -> bool:
165
+ if isinstance(value, bool):
166
+ return value
167
+ if not isinstance(value, str):
168
+ raise MesonException(f'Option "{self.name}" value {value} cannot be converted to a boolean')
169
+ if value.lower() == 'true':
170
+ return True
171
+ if value.lower() == 'false':
172
+ return False
173
+ raise MesonException(f'Option "{self.name}" value {value} is not boolean (true or false).')
174
+
175
+ class UserIntegerOption(UserOption[int]):
176
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
177
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
178
+ min_value, max_value, default_value = value
179
+ self.min_value = min_value
180
+ self.max_value = max_value
181
+ c: T.List[str] = []
182
+ if min_value is not None:
183
+ c.append('>=' + str(min_value))
184
+ if max_value is not None:
185
+ c.append('<=' + str(max_value))
186
+ choices = ', '.join(c)
187
+ super().__init__(name, description, choices, yielding, deprecated)
188
+ self.set_value(default_value)
189
+
190
+ def validate_value(self, value: T.Any) -> int:
191
+ if isinstance(value, str):
192
+ value = self.toint(value)
193
+ if not isinstance(value, int):
194
+ raise MesonException(f'Value {value!r} for option "{self.name}" is not an integer.')
195
+ if self.min_value is not None and value < self.min_value:
196
+ raise MesonException(f'Value {value} for option "{self.name}" is less than minimum value {self.min_value}.')
197
+ if self.max_value is not None and value > self.max_value:
198
+ raise MesonException(f'Value {value} for option "{self.name}" is more than maximum value {self.max_value}.')
199
+ return value
200
+
201
+ def toint(self, valuestring: str) -> int:
202
+ try:
203
+ return int(valuestring)
204
+ except ValueError:
205
+ raise MesonException(f'Value string "{valuestring}" for option "{self.name}" is not convertible to an integer.')
206
+
207
+ class OctalInt(int):
208
+ # NinjaBackend.get_user_option_args uses str() to converts it to a command line option
209
+ # UserUmaskOption.toint() uses int(str, 8) to convert it to an integer
210
+ # So we need to use oct instead of dec here if we do not want values to be misinterpreted.
211
+ def __str__(self) -> str:
212
+ return oct(int(self))
213
+
214
+ class UserUmaskOption(UserIntegerOption, UserOption[T.Union[str, OctalInt]]):
215
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
216
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
217
+ super().__init__(name, description, (0, 0o777, value), yielding, deprecated)
218
+ self.choices = ['preserve', '0000-0777']
219
+
220
+ def printable_value(self) -> str:
221
+ if self.value == 'preserve':
222
+ return self.value
223
+ return format(self.value, '04o')
224
+
225
+ def validate_value(self, value: T.Any) -> T.Union[str, OctalInt]:
226
+ if value == 'preserve':
227
+ return 'preserve'
228
+ return OctalInt(super().validate_value(value))
229
+
230
+ def toint(self, valuestring: T.Union[str, OctalInt]) -> int:
231
+ try:
232
+ return int(valuestring, 8)
233
+ except ValueError as e:
234
+ raise MesonException(f'Invalid mode for option "{self.name}" {e}')
235
+
236
+ class UserComboOption(UserOption[str]):
237
+ def __init__(self, name: str, description: str, choices: T.List[str], value: T.Any,
238
+ yielding: bool = DEFAULT_YIELDING,
239
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
240
+ super().__init__(name, description, choices, yielding, deprecated)
241
+ if not isinstance(self.choices, list):
242
+ raise MesonException(f'Combo choices for option "{self.name}" must be an array.')
243
+ for i in self.choices:
244
+ if not isinstance(i, str):
245
+ raise MesonException(f'Combo choice elements for option "{self.name}" must be strings.')
246
+ self.set_value(value)
247
+
248
+ def validate_value(self, value: T.Any) -> str:
249
+ if value not in self.choices:
250
+ if isinstance(value, bool):
251
+ _type = 'boolean'
252
+ elif isinstance(value, (int, float)):
253
+ _type = 'number'
254
+ else:
255
+ _type = 'string'
256
+ optionsstring = ', '.join([f'"{item}"' for item in self.choices])
257
+ raise MesonException('Value "{}" (of type "{}") for option "{}" is not one of the choices.'
258
+ ' Possible choices are (as string): {}.'.format(
259
+ value, _type, self.name, optionsstring))
260
+ return value
261
+
262
+ class UserArrayOption(UserOption[T.List[str]]):
263
+ def __init__(self, name: str, description: str, value: T.Union[str, T.List[str]],
264
+ split_args: bool = False,
265
+ allow_dups: bool = False, yielding: bool = DEFAULT_YIELDING,
266
+ choices: T.Optional[T.List[str]] = None,
267
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
268
+ super().__init__(name, description, choices if choices is not None else [], yielding, deprecated)
269
+ self.split_args = split_args
270
+ self.allow_dups = allow_dups
271
+ self.set_value(value)
272
+
273
+ def listify(self, value: T.Any) -> T.List[T.Any]:
274
+ try:
275
+ return listify_array_value(value, self.split_args)
276
+ except MesonException as e:
277
+ raise MesonException(f'error in option "{self.name}": {e!s}')
278
+
279
+ def validate_value(self, value: T.Union[str, T.List[str]]) -> T.List[str]:
280
+ newvalue = self.listify(value)
281
+
282
+ if not self.allow_dups and len(set(newvalue)) != len(newvalue):
283
+ msg = 'Duplicated values in array option is deprecated. ' \
284
+ 'This will become a hard error in the future.'
285
+ mlog.deprecation(msg)
286
+ for i in newvalue:
287
+ if not isinstance(i, str):
288
+ raise MesonException(f'String array element "{newvalue!s}" for option "{self.name}" is not a string.')
289
+ if self.choices:
290
+ bad = [x for x in newvalue if x not in self.choices]
291
+ if bad:
292
+ raise MesonException('Value{} "{}" for option "{}" {} not in allowed choices: "{}"'.format(
293
+ '' if len(bad) == 1 else 's',
294
+ ', '.join(bad),
295
+ self.name,
296
+ 'is' if len(bad) == 1 else 'are',
297
+ ', '.join(self.choices))
298
+ )
299
+ return newvalue
300
+
301
+ def extend_value(self, value: T.Union[str, T.List[str]]) -> None:
302
+ """Extend the value with an additional value."""
303
+ new = self.validate_value(value)
304
+ self.set_value(self.value + new)
305
+
306
+
307
+ class UserFeatureOption(UserComboOption):
308
+ static_choices = ['enabled', 'disabled', 'auto']
309
+
310
+ def __init__(self, name: str, description: str, value: T.Any, yielding: bool = DEFAULT_YIELDING,
311
+ deprecated: T.Union[bool, str, T.Dict[str, str], T.List[str]] = False):
312
+ super().__init__(name, description, self.static_choices, value, yielding, deprecated)
313
+ self.name: T.Optional[str] = None # TODO: Refactor options to all store their name
314
+
315
+ def is_enabled(self) -> bool:
316
+ return self.value == 'enabled'
317
+
318
+ def is_disabled(self) -> bool:
319
+ return self.value == 'disabled'
320
+
321
+ def is_auto(self) -> bool:
322
+ return self.value == 'auto'
323
+
324
+ class UserStdOption(UserComboOption):
325
+ '''
326
+ UserOption specific to c_std and cpp_std options. User can set a list of
327
+ STDs in preference order and it selects the first one supported by current
328
+ compiler.
329
+
330
+ For historical reasons, some compilers (msvc) allowed setting a GNU std and
331
+ silently fell back to C std. This is now deprecated. Projects that support
332
+ both GNU and MSVC compilers should set e.g. c_std=gnu11,c11.
333
+
334
+ This is not using self.deprecated mechanism we already have for project
335
+ options because we want to print a warning if ALL values are deprecated, not
336
+ if SOME values are deprecated.
337
+ '''
338
+ def __init__(self, lang: str, all_stds: T.List[str]) -> None:
339
+ self.lang = lang.lower()
340
+ self.all_stds = ['none'] + all_stds
341
+ # Map a deprecated std to its replacement. e.g. gnu11 -> c11.
342
+ self.deprecated_stds: T.Dict[str, str] = {}
343
+ opt_name = 'cpp_std' if lang == 'c++' else f'{lang}_std'
344
+ super().__init__(opt_name, f'{lang} language standard to use', ['none'], 'none')
345
+
346
+ def set_versions(self, versions: T.List[str], gnu: bool = False, gnu_deprecated: bool = False) -> None:
347
+ assert all(std in self.all_stds for std in versions)
348
+ self.choices += versions
349
+ if gnu:
350
+ gnu_stds_map = {f'gnu{std[1:]}': std for std in versions}
351
+ if gnu_deprecated:
352
+ self.deprecated_stds.update(gnu_stds_map)
353
+ else:
354
+ self.choices += gnu_stds_map.keys()
355
+
356
+ def validate_value(self, value: T.Union[str, T.List[str]]) -> str:
357
+ try:
358
+ candidates = listify_array_value(value)
359
+ except MesonException as e:
360
+ raise MesonException(f'error in option "{self.name}": {e!s}')
361
+ unknown = ','.join(std for std in candidates if std not in self.all_stds)
362
+ if unknown:
363
+ raise MesonException(f'Unknown option "{self.name}" value {unknown}. Possible values are {self.all_stds}.')
364
+ # Check first if any of the candidates are not deprecated
365
+ for std in candidates:
366
+ if std in self.choices:
367
+ return std
368
+ # Fallback to a deprecated std if any
369
+ for std in candidates:
370
+ newstd = self.deprecated_stds.get(std)
371
+ if newstd is not None:
372
+ mlog.deprecation(
373
+ f'None of the values {candidates} are supported by the {self.lang} compiler.\n' +
374
+ f'However, the deprecated {std} std currently falls back to {newstd}.\n' +
375
+ 'This will be an error in the future.\n' +
376
+ 'If the project supports both GNU and MSVC compilers, a value such as\n' +
377
+ '"c_std=gnu11,c11" specifies that GNU is preferred but it can safely fallback to plain c11.')
378
+ return newstd
379
+ raise MesonException(f'None of values {candidates} are supported by the {self.lang.upper()} compiler. ' +
380
+ f'Possible values for option "{self.name}" are {self.choices}')
381
+
382
+ @dataclass
383
+ class OptionsView(abc.Mapping):
384
+ '''A view on an options dictionary for a given subproject and with overrides.
385
+ '''
386
+
387
+ # TODO: the typing here could be made more explicit using a TypeDict from
388
+ # python 3.8 or typing_extensions
389
+ options: KeyedOptionDictType
390
+ subproject: T.Optional[str] = None
391
+ overrides: T.Optional[T.Mapping[OptionKey, T.Union[str, int, bool, T.List[str]]]] = None
392
+
393
+ def __getitem__(self, key: OptionKey) -> UserOption:
394
+ # FIXME: This is fundamentally the same algorithm than interpreter.get_option_internal().
395
+ # We should try to share the code somehow.
396
+ key = key.evolve(subproject=self.subproject)
397
+ if not key.is_project():
398
+ opt = self.options.get(key)
399
+ if opt is None or opt.yielding:
400
+ opt = self.options[key.as_root()]
401
+ else:
402
+ opt = self.options[key]
403
+ if opt.yielding:
404
+ opt = self.options.get(key.as_root(), opt)
405
+ if self.overrides:
406
+ override_value = self.overrides.get(key.as_root())
407
+ if override_value is not None:
408
+ opt = copy.copy(opt)
409
+ opt.set_value(override_value)
410
+ return opt
411
+
412
+ def __iter__(self) -> T.Iterator[OptionKey]:
413
+ return iter(self.options)
414
+
415
+ def __len__(self) -> int:
416
+ return len(self.options)
417
+
418
+ class DependencyCacheType(enum.Enum):
419
+
420
+ OTHER = 0
421
+ PKG_CONFIG = 1
422
+ CMAKE = 2
423
+
424
+ @classmethod
425
+ def from_type(cls, dep: 'dependencies.Dependency') -> 'DependencyCacheType':
426
+ # As more types gain search overrides they'll need to be added here
427
+ if dep.type_name == 'pkgconfig':
428
+ return cls.PKG_CONFIG
429
+ if dep.type_name == 'cmake':
430
+ return cls.CMAKE
431
+ return cls.OTHER
432
+
433
+
434
+ class DependencySubCache:
435
+
436
+ def __init__(self, type_: DependencyCacheType):
437
+ self.types = [type_]
438
+ self.__cache: T.Dict[T.Tuple[str, ...], 'dependencies.Dependency'] = {}
439
+
440
+ def __getitem__(self, key: T.Tuple[str, ...]) -> 'dependencies.Dependency':
441
+ return self.__cache[key]
442
+
443
+ def __setitem__(self, key: T.Tuple[str, ...], value: 'dependencies.Dependency') -> None:
444
+ self.__cache[key] = value
445
+
446
+ def __contains__(self, key: T.Tuple[str, ...]) -> bool:
447
+ return key in self.__cache
448
+
449
+ def values(self) -> T.Iterable['dependencies.Dependency']:
450
+ return self.__cache.values()
451
+
452
+
453
+ class DependencyCache:
454
+
455
+ """Class that stores a cache of dependencies.
456
+
457
+ This class is meant to encapsulate the fact that we need multiple keys to
458
+ successfully lookup by providing a simple get/put interface.
459
+ """
460
+
461
+ def __init__(self, builtins: 'KeyedOptionDictType', for_machine: MachineChoice):
462
+ self.__cache: T.MutableMapping[TV_DepID, DependencySubCache] = OrderedDict()
463
+ self.__builtins = builtins
464
+ self.__pkg_conf_key = OptionKey('pkg_config_path', machine=for_machine)
465
+ self.__cmake_key = OptionKey('cmake_prefix_path', machine=for_machine)
466
+
467
+ def __calculate_subkey(self, type_: DependencyCacheType) -> T.Tuple[str, ...]:
468
+ data: T.Dict[DependencyCacheType, T.List[str]] = {
469
+ DependencyCacheType.PKG_CONFIG: stringlistify(self.__builtins[self.__pkg_conf_key].value),
470
+ DependencyCacheType.CMAKE: stringlistify(self.__builtins[self.__cmake_key].value),
471
+ DependencyCacheType.OTHER: [],
472
+ }
473
+ assert type_ in data, 'Someone forgot to update subkey calculations for a new type'
474
+ return tuple(data[type_])
475
+
476
+ def __iter__(self) -> T.Iterator['TV_DepID']:
477
+ return self.keys()
478
+
479
+ def put(self, key: 'TV_DepID', dep: 'dependencies.Dependency') -> None:
480
+ t = DependencyCacheType.from_type(dep)
481
+ if key not in self.__cache:
482
+ self.__cache[key] = DependencySubCache(t)
483
+ subkey = self.__calculate_subkey(t)
484
+ self.__cache[key][subkey] = dep
485
+
486
+ def get(self, key: 'TV_DepID') -> T.Optional['dependencies.Dependency']:
487
+ """Get a value from the cache.
488
+
489
+ If there is no cache entry then None will be returned.
490
+ """
491
+ try:
492
+ val = self.__cache[key]
493
+ except KeyError:
494
+ return None
495
+
496
+ for t in val.types:
497
+ subkey = self.__calculate_subkey(t)
498
+ try:
499
+ return val[subkey]
500
+ except KeyError:
501
+ pass
502
+ return None
503
+
504
+ def values(self) -> T.Iterator['dependencies.Dependency']:
505
+ for c in self.__cache.values():
506
+ yield from c.values()
507
+
508
+ def keys(self) -> T.Iterator['TV_DepID']:
509
+ return iter(self.__cache.keys())
510
+
511
+ def items(self) -> T.Iterator[T.Tuple['TV_DepID', T.List['dependencies.Dependency']]]:
512
+ for k, v in self.__cache.items():
513
+ vs: T.List[dependencies.Dependency] = []
514
+ for t in v.types:
515
+ subkey = self.__calculate_subkey(t)
516
+ if subkey in v:
517
+ vs.append(v[subkey])
518
+ yield k, vs
519
+
520
+ def clear(self) -> None:
521
+ self.__cache.clear()
522
+
523
+
524
+ class CMakeStateCache:
525
+ """Class that stores internal CMake compiler states.
526
+
527
+ This cache is used to reduce the startup overhead of CMake by caching
528
+ all internal CMake compiler variables.
529
+ """
530
+
531
+ def __init__(self) -> None:
532
+ self.__cache: T.Dict[str, T.Dict[str, T.List[str]]] = {}
533
+ self.cmake_cache: T.Dict[str, 'CMakeCacheEntry'] = {}
534
+
535
+ def __iter__(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
536
+ return iter(self.__cache.items())
537
+
538
+ def items(self) -> T.Iterator[T.Tuple[str, T.Dict[str, T.List[str]]]]:
539
+ return iter(self.__cache.items())
540
+
541
+ def update(self, language: str, variables: T.Dict[str, T.List[str]]):
542
+ if language not in self.__cache:
543
+ self.__cache[language] = {}
544
+ self.__cache[language].update(variables)
545
+
546
+ @property
547
+ def languages(self) -> T.Set[str]:
548
+ return set(self.__cache.keys())
549
+
550
+
551
+ # Can't bind this near the class method it seems, sadly.
552
+ _V = T.TypeVar('_V')
553
+
554
+ # This class contains all data that must persist over multiple
555
+ # invocations of Meson. It is roughly the same thing as
556
+ # cmakecache.
557
+
558
+ class CoreData:
559
+
560
+ def __init__(self, options: SharedCMDOptions, scratch_dir: str, meson_command: T.List[str]):
561
+ self.lang_guids = {
562
+ 'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
563
+ 'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
564
+ 'cpp': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942',
565
+ 'test': '3AC096D0-A1C2-E12C-1390-A8335801FDAB',
566
+ 'directory': '2150E333-8FDC-42A3-9474-1A3956D46DE8',
567
+ }
568
+ self.test_guid = str(uuid.uuid4()).upper()
569
+ self.regen_guid = str(uuid.uuid4()).upper()
570
+ self.install_guid = str(uuid.uuid4()).upper()
571
+ self.meson_command = meson_command
572
+ self.target_guids = {}
573
+ self.version = version
574
+ self.options: 'MutableKeyedOptionDictType' = {}
575
+ self.is_build_only = False
576
+ self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
577
+ self.compilers: PerMachine[T.Dict[str, Compiler]] = PerMachine(OrderedDict(), OrderedDict())
578
+
579
+ # Stores the (name, hash) of the options file, The name will be either
580
+ # "meson_options.txt" or "meson.options".
581
+ # This is used by mconf to reload the option file if it's changed.
582
+ self.options_files: T.Dict[SubProject, T.Optional[T.Tuple[str, str]]] = {}
583
+
584
+ # Set of subprojects that have already been initialized once, this is
585
+ # required to be stored and reloaded with the coredata, as we don't
586
+ # want to overwrite options for such subprojects.
587
+ self.initialized_subprojects: T.Set[str] = set()
588
+
589
+ # For host == build configurations these caches should be the same.
590
+ self.deps: PerMachine[DependencyCache] = PerMachineDefaultable.default(
591
+ self.is_cross_build(),
592
+ DependencyCache(self.options, MachineChoice.BUILD),
593
+ DependencyCache(self.options, MachineChoice.HOST))
594
+
595
+ self.compiler_check_cache: T.Dict['CompilerCheckCacheKey', 'CompileResult'] = OrderedDict()
596
+ self.run_check_cache: T.Dict['RunCheckCacheKey', 'RunResult'] = OrderedDict()
597
+
598
+ # CMake cache
599
+ self.cmake_cache: PerMachine[CMakeStateCache] = PerMachine(CMakeStateCache(), CMakeStateCache())
600
+
601
+ # Only to print a warning if it changes between Meson invocations.
602
+ self.config_files = self.__load_config_files(options, scratch_dir, 'native')
603
+ self.builtin_options_libdir_cross_fixup()
604
+ self.init_builtins('')
605
+
606
+ def copy_as_build(self) -> CoreData:
607
+ """Create a copy if this coredata, but for the build machine.
608
+
609
+ If this is not a cross build, then a reference to self will be returned
610
+ instead.
611
+ """
612
+ if not self.is_cross_build():
613
+ return self
614
+
615
+ new = copy.copy(self)
616
+ new.is_build_only = True
617
+
618
+ new.options = {}
619
+ new.init_builtins('')
620
+ new.options.update({k: v for k, v in self.options.items()
621
+ if k.machine is MachineChoice.HOST and not self.is_per_machine_option(k)})
622
+ new.options.update({k.as_host(): v for k, v in self.options.items()
623
+ if k.machine is MachineChoice.BUILD})
624
+ new.options.update({k: v for k, v in self.options.items()
625
+ if k.machine is MachineChoice.BUILD})
626
+
627
+ # Use only the build deps, not any host ones
628
+ new.deps = PerMachineDefaultable(self.deps.build).default_missing()
629
+ new.compilers = PerMachineDefaultable(self.compilers.build).default_missing()
630
+ new.cmake_cache = PerMachineDefaultable(self.cmake_cache.build).default_missing()
631
+
632
+ # Drop any cross files, since this is not a cross compile
633
+ new.cross_files = []
634
+
635
+ return new
636
+
637
+ def merge(self, other: CoreData) -> None:
638
+ build_only_boundary = not self.is_build_only and other.is_build_only
639
+ if not build_only_boundary:
640
+ return
641
+
642
+ self.options.update({k: v for k, v in other.options.items()
643
+ if k.machine is MachineChoice.HOST and not self.is_per_machine_option(k)})
644
+ self.options.update({k: v for k, v in other.options.items()
645
+ if k.machine is MachineChoice.BUILD})
646
+ self.options.update({k.as_build(): v for k, v in other.options.items()
647
+ if k.machine is MachineChoice.HOST and k.subproject and k.is_project()})
648
+
649
+ @staticmethod
650
+ def __load_config_files(options: SharedCMDOptions, scratch_dir: str, ftype: str) -> T.List[str]:
651
+ # Need to try and make the passed filenames absolute because when the
652
+ # files are parsed later we'll have chdir()d.
653
+ if ftype == 'cross':
654
+ filenames = options.cross_file
655
+ else:
656
+ filenames = options.native_file
657
+
658
+ if not filenames:
659
+ return []
660
+
661
+ found_invalid: T.List[str] = []
662
+ missing: T.List[str] = []
663
+ real: T.List[str] = []
664
+ for i, f in enumerate(filenames):
665
+ f = os.path.expanduser(os.path.expandvars(f))
666
+ if os.path.exists(f):
667
+ if os.path.isfile(f):
668
+ real.append(os.path.abspath(f))
669
+ continue
670
+ elif os.path.isdir(f):
671
+ found_invalid.append(os.path.abspath(f))
672
+ else:
673
+ # in this case we've been passed some kind of pipe, copy
674
+ # the contents of that file into the meson private (scratch)
675
+ # directory so that it can be re-read when wiping/reconfiguring
676
+ copy = os.path.join(scratch_dir, f'{uuid.uuid4()}.{ftype}.ini')
677
+ with open(f, encoding='utf-8') as rf:
678
+ with open(copy, 'w', encoding='utf-8') as wf:
679
+ wf.write(rf.read())
680
+ real.append(copy)
681
+
682
+ # Also replace the command line argument, as the pipe
683
+ # probably won't exist on reconfigure
684
+ filenames[i] = copy
685
+ continue
686
+ if sys.platform != 'win32':
687
+ paths = [
688
+ os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share')),
689
+ ] + os.environ.get('XDG_DATA_DIRS', '/usr/local/share:/usr/share').split(':')
690
+ for path in paths:
691
+ path_to_try = os.path.join(path, 'meson', ftype, f)
692
+ if os.path.isfile(path_to_try):
693
+ real.append(path_to_try)
694
+ break
695
+ else:
696
+ missing.append(f)
697
+ else:
698
+ missing.append(f)
699
+
700
+ if missing:
701
+ if found_invalid:
702
+ mlog.log('Found invalid candidates for', ftype, 'file:', *found_invalid)
703
+ mlog.log('Could not find any valid candidate for', ftype, 'files:', *missing)
704
+ raise MesonException(f'Cannot find specified {ftype} file: {f}')
705
+ return real
706
+
707
+ def builtin_options_libdir_cross_fixup(self) -> None:
708
+ # By default set libdir to "lib" when cross compiling since
709
+ # getting the "system default" is always wrong on multiarch
710
+ # platforms as it gets a value like lib/x86_64-linux-gnu.
711
+ if self.cross_files:
712
+ BUILTIN_OPTIONS[OptionKey('libdir')].default = 'lib'
713
+
714
+ def sanitize_prefix(self, prefix: str) -> str:
715
+ prefix = os.path.expanduser(prefix)
716
+ if not os.path.isabs(prefix):
717
+ raise MesonException(f'prefix value {prefix!r} must be an absolute path')
718
+ if prefix.endswith('/') or prefix.endswith('\\'):
719
+ # On Windows we need to preserve the trailing slash if the
720
+ # string is of type 'C:\' because 'C:' is not an absolute path.
721
+ if len(prefix) == 3 and prefix[1] == ':':
722
+ pass
723
+ # If prefix is a single character, preserve it since it is
724
+ # the root directory.
725
+ elif len(prefix) == 1:
726
+ pass
727
+ else:
728
+ prefix = prefix[:-1]
729
+ return prefix
730
+
731
+ def sanitize_dir_option_value(self, prefix: str, option: OptionKey, value: T.Any) -> T.Any:
732
+ '''
733
+ If the option is an installation directory option, the value is an
734
+ absolute path and resides within prefix, return the value
735
+ as a path relative to the prefix. Otherwise, return it as is.
736
+
737
+ This way everyone can do f.ex, get_option('libdir') and usually get
738
+ the library directory relative to prefix, even though it really
739
+ should not be relied upon.
740
+ '''
741
+ try:
742
+ value = PurePath(value)
743
+ except TypeError:
744
+ return value
745
+ if option.name.endswith('dir') and value.is_absolute() and \
746
+ option not in BUILTIN_DIR_NOPREFIX_OPTIONS:
747
+ try:
748
+ # Try to relativize the path.
749
+ value = value.relative_to(prefix)
750
+ except ValueError:
751
+ # Path is not relative, let’s keep it as is.
752
+ pass
753
+ if '..' in value.parts:
754
+ raise MesonException(
755
+ f'The value of the \'{option}\' option is \'{value}\' but '
756
+ 'directory options are not allowed to contain \'..\'.\n'
757
+ f'If you need a path outside of the {prefix!r} prefix, '
758
+ 'please use an absolute path.'
759
+ )
760
+ # .as_posix() keeps the posix-like file separators Meson uses.
761
+ return value.as_posix()
762
+
763
+ def init_builtins(self, subproject: str) -> None:
764
+ # Create builtin options with default values
765
+ for key, opt in BUILTIN_OPTIONS.items():
766
+ self.add_builtin_option(self.options, key.evolve(subproject=subproject), opt)
767
+ for for_machine in iter(MachineChoice):
768
+ for key, opt in BUILTIN_OPTIONS_PER_MACHINE.items():
769
+ self.add_builtin_option(self.options, key.evolve(subproject=subproject, machine=for_machine), opt)
770
+
771
+ @staticmethod
772
+ def add_builtin_option(opts_map: 'MutableKeyedOptionDictType', key: OptionKey,
773
+ opt: 'BuiltinOption') -> None:
774
+ if key.subproject:
775
+ if opt.yielding:
776
+ # This option is global and not per-subproject
777
+ return
778
+ value = opts_map[key.as_root()].value
779
+ else:
780
+ value = None
781
+ opts_map[key] = opt.init_option(key, value, default_prefix())
782
+
783
+ def init_backend_options(self, backend_name: str) -> None:
784
+ if backend_name == 'ninja':
785
+ self.options[OptionKey('backend_max_links')] = UserIntegerOption(
786
+ 'backend_max_links',
787
+ 'Maximum number of linker processes to run or 0 for no '
788
+ 'limit',
789
+ (0, None, 0))
790
+ elif backend_name.startswith('vs'):
791
+ self.options[OptionKey('backend_startup_project')] = UserStringOption(
792
+ 'backend_startup_project',
793
+ 'Default project to execute in Visual Studio',
794
+ '')
795
+
796
+ def get_option(self, key: OptionKey) -> T.Union[T.List[str], str, int, bool, WrapMode]:
797
+ try:
798
+ v = self.options[key].value
799
+ if key.name == 'wrap_mode':
800
+ return WrapMode[v]
801
+ return v
802
+ except KeyError:
803
+ pass
804
+
805
+ try:
806
+ v = self.options[key.as_root()]
807
+ if v.yielding:
808
+ if key.name == 'wrap_mode':
809
+ return WrapMode[v.value]
810
+ return v.value
811
+ except KeyError:
812
+ pass
813
+
814
+ raise MesonException(f'Tried to get unknown builtin option {str(key)}')
815
+
816
+ def set_option(self, key: OptionKey, value, first_invocation: bool = False) -> bool:
817
+ dirty = False
818
+ if key.is_builtin():
819
+ if key.name == 'prefix':
820
+ value = self.sanitize_prefix(value)
821
+ else:
822
+ prefix = self.options[OptionKey('prefix')].value
823
+ value = self.sanitize_dir_option_value(prefix, key, value)
824
+
825
+ try:
826
+ opt = self.options[key]
827
+ except KeyError:
828
+ raise MesonException(f'Tried to set unknown builtin option {str(key)}')
829
+
830
+ if opt.deprecated is True:
831
+ mlog.deprecation(f'Option {key.name!r} is deprecated')
832
+ elif isinstance(opt.deprecated, list):
833
+ for v in opt.listify(value):
834
+ if v in opt.deprecated:
835
+ mlog.deprecation(f'Option {key.name!r} value {v!r} is deprecated')
836
+ elif isinstance(opt.deprecated, dict):
837
+ def replace(v):
838
+ newvalue = opt.deprecated.get(v)
839
+ if newvalue is not None:
840
+ mlog.deprecation(f'Option {key.name!r} value {v!r} is replaced by {newvalue!r}')
841
+ return newvalue
842
+ return v
843
+ newvalue = [replace(v) for v in opt.listify(value)]
844
+ value = ','.join(newvalue)
845
+ elif isinstance(opt.deprecated, str):
846
+ # Option is deprecated and replaced by another. Note that a project
847
+ # option could be replaced by a built-in or module option, which is
848
+ # why we use OptionKey.from_string(newname) instead of
849
+ # key.evolve(newname). We set the value on both the old and new names,
850
+ # assuming they accept the same value. That could for example be
851
+ # achieved by adding the values from old option as deprecated on the
852
+ # new option, for example in the case of boolean option is replaced
853
+ # by a feature option with a different name.
854
+ newname = opt.deprecated
855
+ newkey = OptionKey.from_string(newname).evolve(subproject=key.subproject)
856
+ mlog.deprecation(f'Option {key.name!r} is replaced by {newname!r}')
857
+ dirty |= self.set_option(newkey, value, first_invocation)
858
+
859
+ changed = opt.set_value(value)
860
+ if changed and opt.readonly and not first_invocation:
861
+ raise MesonException(f'Tried modify read only option {str(key)!r}')
862
+ dirty |= changed
863
+
864
+ if key.name == 'buildtype':
865
+ dirty |= self._set_others_from_buildtype(value)
866
+
867
+ return dirty
868
+
869
+ def clear_cache(self) -> None:
870
+ self.deps.host.clear()
871
+ self.deps.build.clear()
872
+ self.compiler_check_cache.clear()
873
+ self.run_check_cache.clear()
874
+
875
+ def get_nondefault_buildtype_args(self) -> T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]]:
876
+ result: T.List[T.Union[T.Tuple[str, str, str], T.Tuple[str, bool, bool]]] = []
877
+ value = self.options[OptionKey('buildtype')].value
878
+ if value == 'plain':
879
+ opt = 'plain'
880
+ debug = False
881
+ elif value == 'debug':
882
+ opt = '0'
883
+ debug = True
884
+ elif value == 'debugoptimized':
885
+ opt = '2'
886
+ debug = True
887
+ elif value == 'release':
888
+ opt = '3'
889
+ debug = False
890
+ elif value == 'minsize':
891
+ opt = 's'
892
+ debug = True
893
+ else:
894
+ assert value == 'custom'
895
+ return []
896
+ actual_opt = self.options[OptionKey('optimization')].value
897
+ actual_debug = self.options[OptionKey('debug')].value
898
+ if actual_opt != opt:
899
+ result.append(('optimization', actual_opt, opt))
900
+ if actual_debug != debug:
901
+ result.append(('debug', actual_debug, debug))
902
+ return result
903
+
904
+ def _set_others_from_buildtype(self, value: str) -> bool:
905
+ dirty = False
906
+
907
+ if value == 'plain':
908
+ opt = 'plain'
909
+ debug = False
910
+ elif value == 'debug':
911
+ opt = '0'
912
+ debug = True
913
+ elif value == 'debugoptimized':
914
+ opt = '2'
915
+ debug = True
916
+ elif value == 'release':
917
+ opt = '3'
918
+ debug = False
919
+ elif value == 'minsize':
920
+ opt = 's'
921
+ debug = True
922
+ else:
923
+ assert value == 'custom'
924
+ return False
925
+
926
+ dirty |= self.options[OptionKey('optimization')].set_value(opt)
927
+ dirty |= self.options[OptionKey('debug')].set_value(debug)
928
+
929
+ return dirty
930
+
931
+ @staticmethod
932
+ def is_per_machine_option(optname: OptionKey) -> bool:
933
+ if optname.subproject and optname.is_project():
934
+ return True
935
+ if optname.as_host() in BUILTIN_OPTIONS_PER_MACHINE:
936
+ return True
937
+ return optname.lang is not None
938
+
939
+ def get_external_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
940
+ # mypy cannot analyze type of OptionKey
941
+ return T.cast('T.List[str]', self.options[OptionKey('args', machine=for_machine, lang=lang)].value)
942
+
943
+ def get_external_link_args(self, for_machine: MachineChoice, lang: str) -> T.List[str]:
944
+ # mypy cannot analyze type of OptionKey
945
+ return T.cast('T.List[str]', self.options[OptionKey('link_args', machine=for_machine, lang=lang)].value)
946
+
947
+ def update_project_options(self, options: 'MutableKeyedOptionDictType', subproject: SubProject) -> None:
948
+ for key, value in options.items():
949
+ if not key.is_project():
950
+ continue
951
+ if key not in self.options:
952
+ self.options[key] = value
953
+ continue
954
+ if key.subproject != subproject:
955
+ raise MesonBugException(f'Tried to set an option for subproject {key.subproject} from {subproject}!')
956
+
957
+ oldval = self.options[key]
958
+ if type(oldval) is not type(value):
959
+ self.options[key] = value
960
+ elif oldval.choices != value.choices:
961
+ # If the choices have changed, use the new value, but attempt
962
+ # to keep the old options. If they are not valid keep the new
963
+ # defaults but warn.
964
+ self.options[key] = value
965
+ try:
966
+ value.set_value(oldval.value)
967
+ except MesonException:
968
+ mlog.warning(f'Old value(s) of {key} are no longer valid, resetting to default ({value.value}).',
969
+ fatal=False)
970
+
971
+ # Find any extranious keys for this project and remove them
972
+ for key in list(self.options.keys() - options.keys()):
973
+ if key.is_project() and key.subproject == subproject:
974
+ del self.options[key]
975
+
976
+ def is_cross_build(self, when_building_for: MachineChoice = MachineChoice.HOST) -> bool:
977
+ if when_building_for == MachineChoice.BUILD:
978
+ return False
979
+ return len(self.cross_files) > 0
980
+
981
+ def copy_build_options_from_regular_ones(self) -> bool:
982
+ dirty = False
983
+ assert not self.is_cross_build()
984
+ for k in BUILTIN_OPTIONS_PER_MACHINE:
985
+ o = self.options[k]
986
+ dirty |= self.options[k.as_build()].set_value(o.value)
987
+ for bk, bv in self.options.items():
988
+ if bk.machine is MachineChoice.BUILD:
989
+ hk = bk.as_host()
990
+ try:
991
+ hv = self.options[hk]
992
+ dirty |= bv.set_value(hv.value)
993
+ except KeyError:
994
+ continue
995
+
996
+ return dirty
997
+
998
+ def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', first_invocation: bool = False) -> bool:
999
+ dirty = False
1000
+ if not self.is_cross_build():
1001
+ options = {k: v for k, v in options.items() if k.machine is not MachineChoice.BUILD}
1002
+ # Set prefix first because it's needed to sanitize other options
1003
+ pfk = OptionKey('prefix')
1004
+ if pfk in options:
1005
+ prefix = self.sanitize_prefix(options[pfk])
1006
+ dirty |= self.options[OptionKey('prefix')].set_value(prefix)
1007
+ for key in BUILTIN_DIR_NOPREFIX_OPTIONS:
1008
+ if key not in options:
1009
+ dirty |= self.options[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
1010
+
1011
+ unknown_options: T.List[OptionKey] = []
1012
+ for k, v in options.items():
1013
+ if k == pfk:
1014
+ continue
1015
+ elif k in self.options:
1016
+ dirty |= self.set_option(k, v, first_invocation)
1017
+ elif k.machine != MachineChoice.BUILD and k.type != OptionType.COMPILER:
1018
+ unknown_options.append(k)
1019
+ if unknown_options:
1020
+ unknown_options_str = ', '.join(sorted(str(s) for s in unknown_options))
1021
+ sub = f'In subproject {subproject}: ' if subproject else ''
1022
+ raise MesonException(f'{sub}Unknown options: "{unknown_options_str}"')
1023
+
1024
+ if not self.is_cross_build():
1025
+ dirty |= self.copy_build_options_from_regular_ones()
1026
+
1027
+ return dirty
1028
+
1029
+ def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None:
1030
+ from .compilers import base_options
1031
+
1032
+ # Main project can set default options on subprojects, but subprojects
1033
+ # can only set default options on themselves.
1034
+ # Preserve order: if env.options has 'buildtype' it must come after
1035
+ # 'optimization' if it is in default_options.
1036
+ options: T.MutableMapping[OptionKey, T.Any] = OrderedDict()
1037
+ for k, v in default_options.items():
1038
+ if not subproject or k.subproject == subproject:
1039
+ options[k] = v
1040
+ options.update(env.options)
1041
+ env.options = options
1042
+
1043
+ # Create a subset of options, keeping only project and builtin
1044
+ # options for this subproject.
1045
+ # Language and backend specific options will be set later when adding
1046
+ # languages and setting the backend (builtin options must be set first
1047
+ # to know which backend we'll use).
1048
+ options = OrderedDict()
1049
+
1050
+ for k, v in env.options.items():
1051
+ # If this is a subproject, don't use other subproject options
1052
+ if k.subproject and k.subproject != subproject:
1053
+ continue
1054
+ # If the option is a builtin and is yielding then it's not allowed per subproject.
1055
+ #
1056
+ # Always test this using the HOST machine, as many builtin options
1057
+ # are not valid for the BUILD machine, but the yielding value does
1058
+ # not differ between them even when they are valid for both.
1059
+ if subproject and k.is_builtin() and self.options[k.evolve(subproject='', machine=MachineChoice.HOST)].yielding:
1060
+ continue
1061
+ # Skip base, compiler, and backend options, they are handled when
1062
+ # adding languages and setting backend.
1063
+ if k.type in {OptionType.COMPILER, OptionType.BACKEND}:
1064
+ continue
1065
+ if k.type == OptionType.BASE and k.as_root() in base_options:
1066
+ # set_options will report unknown base options
1067
+ continue
1068
+ options[k] = v
1069
+
1070
+ self.set_options(options, subproject=subproject, first_invocation=env.first_invocation)
1071
+
1072
+ def add_compiler_options(self, options: MutableKeyedOptionDictType, lang: str, for_machine: MachineChoice,
1073
+ env: Environment, subproject: str) -> None:
1074
+ for k, o in options.items():
1075
+ value = env.options.get(k)
1076
+ if value is not None:
1077
+ o.set_value(value)
1078
+ if not subproject:
1079
+ self.options[k] = o # override compiler option on reconfigure
1080
+ self.options.setdefault(k, o)
1081
+
1082
+ if subproject:
1083
+ sk = k.evolve(subproject=subproject)
1084
+ value = env.options.get(sk) or value
1085
+ if value is not None:
1086
+ o.set_value(value)
1087
+ self.options[sk] = o # override compiler option on reconfigure
1088
+ self.options.setdefault(sk, o)
1089
+
1090
+ def add_lang_args(self, lang: str, comp: T.Type['Compiler'],
1091
+ for_machine: MachineChoice, env: 'Environment') -> None:
1092
+ """Add global language arguments that are needed before compiler/linker detection."""
1093
+ from .compilers import compilers
1094
+ # These options are all new at this point, because the compiler is
1095
+ # responsible for adding its own options, thus calling
1096
+ # `self.options.update()`` is perfectly safe.
1097
+ self.options.update(compilers.get_global_options(lang, comp, for_machine, env))
1098
+
1099
+ def process_compiler_options(self, lang: str, comp: Compiler, env: Environment, subproject: str) -> None:
1100
+ from . import compilers
1101
+
1102
+ self.add_compiler_options(comp.get_options(), lang, comp.for_machine, env, subproject)
1103
+
1104
+ enabled_opts: T.List[OptionKey] = []
1105
+ for key in comp.base_options:
1106
+ if subproject:
1107
+ skey = key.evolve(subproject=subproject)
1108
+ else:
1109
+ skey = key
1110
+ if skey not in self.options:
1111
+ self.options[skey] = copy.deepcopy(compilers.base_options[key])
1112
+ if skey in env.options:
1113
+ self.options[skey].set_value(env.options[skey])
1114
+ enabled_opts.append(skey)
1115
+ elif subproject and key in env.options:
1116
+ self.options[skey].set_value(env.options[key])
1117
+ enabled_opts.append(skey)
1118
+ if subproject and key not in self.options:
1119
+ self.options[key] = copy.deepcopy(self.options[skey])
1120
+ elif skey in env.options:
1121
+ self.options[skey].set_value(env.options[skey])
1122
+ elif subproject and key in env.options:
1123
+ self.options[skey].set_value(env.options[key])
1124
+ self.emit_base_options_warnings(enabled_opts)
1125
+
1126
+ def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
1127
+ if OptionKey('b_bitcode') in enabled_opts:
1128
+ mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as \'b_asneeded\' have been disabled.', fatal=False)
1129
+ mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.', fatal=False)
1130
+
1131
+ class CmdLineFileParser(configparser.ConfigParser):
1132
+ def __init__(self) -> None:
1133
+ # We don't want ':' as key delimiter, otherwise it would break when
1134
+ # storing subproject options like "subproject:option=value"
1135
+ super().__init__(delimiters=['='], interpolation=None)
1136
+
1137
+ def read(self, filenames: T.Union['StrOrBytesPath', T.Iterable['StrOrBytesPath']], encoding: T.Optional[str] = 'utf-8') -> T.List[str]:
1138
+ return super().read(filenames, encoding)
1139
+
1140
+ def optionxform(self, optionstr: str) -> str:
1141
+ # Don't call str.lower() on keys
1142
+ return optionstr
1143
+
1144
+ class MachineFileParser():
1145
+ def __init__(self, filenames: T.List[str], sourcedir: str) -> None:
1146
+ self.parser = CmdLineFileParser()
1147
+ self.constants: T.Dict[str, T.Union[str, bool, int, T.List[str]]] = {'True': True, 'False': False}
1148
+ self.sections: T.Dict[str, T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = {}
1149
+
1150
+ for fname in filenames:
1151
+ with open(fname, encoding='utf-8') as f:
1152
+ content = f.read()
1153
+ content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir)
1154
+ content = content.replace('@DIRNAME@', os.path.dirname(fname))
1155
+ try:
1156
+ self.parser.read_string(content, fname)
1157
+ except configparser.Error as e:
1158
+ raise EnvironmentException(f'Malformed machine file: {e}')
1159
+
1160
+ # Parse [constants] first so they can be used in other sections
1161
+ if self.parser.has_section('constants'):
1162
+ self.constants.update(self._parse_section('constants'))
1163
+
1164
+ for s in self.parser.sections():
1165
+ if s == 'constants':
1166
+ continue
1167
+ self.sections[s] = self._parse_section(s)
1168
+
1169
+ def _parse_section(self, s: str) -> T.Dict[str, T.Union[str, bool, int, T.List[str]]]:
1170
+ self.scope = self.constants.copy()
1171
+ section: T.Dict[str, T.Union[str, bool, int, T.List[str]]] = {}
1172
+ for entry, value in self.parser.items(s):
1173
+ if ' ' in entry or '\t' in entry or "'" in entry or '"' in entry:
1174
+ raise EnvironmentException(f'Malformed variable name {entry!r} in machine file.')
1175
+ # Windows paths...
1176
+ value = value.replace('\\', '\\\\')
1177
+ try:
1178
+ ast = mparser.Parser(value, 'machinefile').parse()
1179
+ if not ast.lines:
1180
+ raise EnvironmentException('value cannot be empty')
1181
+ res = self._evaluate_statement(ast.lines[0])
1182
+ except MesonException as e:
1183
+ raise EnvironmentException(f'Malformed value in machine file variable {entry!r}: {str(e)}.')
1184
+ except KeyError as e:
1185
+ raise EnvironmentException(f'Undefined constant {e.args[0]!r} in machine file variable {entry!r}.')
1186
+ section[entry] = res
1187
+ self.scope[entry] = res
1188
+ return section
1189
+
1190
+ def _evaluate_statement(self, node: mparser.BaseNode) -> T.Union[str, bool, int, T.List[str]]:
1191
+ if isinstance(node, (mparser.BaseStringNode)):
1192
+ return node.value
1193
+ elif isinstance(node, mparser.BooleanNode):
1194
+ return node.value
1195
+ elif isinstance(node, mparser.NumberNode):
1196
+ return node.value
1197
+ elif isinstance(node, mparser.ParenthesizedNode):
1198
+ return self._evaluate_statement(node.inner)
1199
+ elif isinstance(node, mparser.ArrayNode):
1200
+ # TODO: This is where recursive types would come in handy
1201
+ return [self._evaluate_statement(arg) for arg in node.args.arguments]
1202
+ elif isinstance(node, mparser.IdNode):
1203
+ return self.scope[node.value]
1204
+ elif isinstance(node, mparser.ArithmeticNode):
1205
+ l = self._evaluate_statement(node.left)
1206
+ r = self._evaluate_statement(node.right)
1207
+ if node.operation == 'add':
1208
+ if (isinstance(l, str) and isinstance(r, str)) or \
1209
+ (isinstance(l, list) and isinstance(r, list)):
1210
+ return l + r
1211
+ elif node.operation == 'div':
1212
+ if isinstance(l, str) and isinstance(r, str):
1213
+ return os.path.join(l, r)
1214
+ raise EnvironmentException('Unsupported node type')
1215
+
1216
+ def parse_machine_files(filenames: T.List[str], sourcedir: str):
1217
+ parser = MachineFileParser(filenames, sourcedir)
1218
+ return parser.sections
1219
+
1220
+ def get_cmd_line_file(build_dir: str) -> str:
1221
+ return os.path.join(build_dir, 'meson-private', 'cmd_line.txt')
1222
+
1223
+ def read_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None:
1224
+ filename = get_cmd_line_file(build_dir)
1225
+ if not os.path.isfile(filename):
1226
+ return
1227
+
1228
+ config = CmdLineFileParser()
1229
+ config.read(filename)
1230
+
1231
+ # Do a copy because config is not really a dict. options.cmd_line_options
1232
+ # overrides values from the file.
1233
+ d = {OptionKey.from_string(k): v for k, v in config['options'].items()}
1234
+ d.update(options.cmd_line_options)
1235
+ options.cmd_line_options = d
1236
+
1237
+ properties = config['properties']
1238
+ if not options.cross_file:
1239
+ options.cross_file = ast.literal_eval(properties.get('cross_file', '[]'))
1240
+ if not options.native_file:
1241
+ # This will be a string in the form: "['first', 'second', ...]", use
1242
+ # literal_eval to get it into the list of strings.
1243
+ options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
1244
+
1245
+ def write_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None:
1246
+ filename = get_cmd_line_file(build_dir)
1247
+ config = CmdLineFileParser()
1248
+
1249
+ properties: OrderedDict[str, str] = OrderedDict()
1250
+ if options.cross_file:
1251
+ properties['cross_file'] = options.cross_file
1252
+ if options.native_file:
1253
+ properties['native_file'] = options.native_file
1254
+
1255
+ config['options'] = {str(k): str(v) for k, v in options.cmd_line_options.items()}
1256
+ config['properties'] = properties
1257
+ with open(filename, 'w', encoding='utf-8') as f:
1258
+ config.write(f)
1259
+
1260
+ def update_cmd_line_file(build_dir: str, options: SharedCMDOptions) -> None:
1261
+ filename = get_cmd_line_file(build_dir)
1262
+ config = CmdLineFileParser()
1263
+ config.read(filename)
1264
+ config['options'].update({str(k): str(v) for k, v in options.cmd_line_options.items()})
1265
+ with open(filename, 'w', encoding='utf-8') as f:
1266
+ config.write(f)
1267
+
1268
+ def format_cmd_line_options(options: SharedCMDOptions) -> str:
1269
+ cmdline = ['-D{}={}'.format(str(k), v) for k, v in options.cmd_line_options.items()]
1270
+ if options.cross_file:
1271
+ cmdline += [f'--cross-file={f}' for f in options.cross_file]
1272
+ if options.native_file:
1273
+ cmdline += [f'--native-file={f}' for f in options.native_file]
1274
+ return ' '.join([shlex.quote(x) for x in cmdline])
1275
+
1276
+ def major_versions_differ(v1: str, v2: str) -> bool:
1277
+ v1_major, v1_minor = v1.rsplit('.', 1)
1278
+ v2_major, v2_minor = v2.rsplit('.', 1)
1279
+ # Major version differ, or one is development version but not the other.
1280
+ return v1_major != v2_major or ('99' in {v1_minor, v2_minor} and v1_minor != v2_minor)
1281
+
1282
+ def load(build_dir: str, suggest_reconfigure: bool = True) -> CoreData:
1283
+ filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
1284
+ return pickle_load(filename, 'Coredata', CoreData, suggest_reconfigure)
1285
+
1286
+
1287
+ def save(obj: CoreData, build_dir: str) -> str:
1288
+ filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
1289
+ prev_filename = filename + '.prev'
1290
+ tempfilename = filename + '~'
1291
+ if major_versions_differ(obj.version, version):
1292
+ raise MesonException('Fatal version mismatch corruption.')
1293
+ if os.path.exists(filename):
1294
+ import shutil
1295
+ shutil.copyfile(filename, prev_filename)
1296
+ with open(tempfilename, 'wb') as f:
1297
+ pickle.dump(obj, f)
1298
+ f.flush()
1299
+ os.fsync(f.fileno())
1300
+ os.replace(tempfilename, filename)
1301
+ return filename
1302
+
1303
+
1304
+ def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
1305
+ for n, b in BUILTIN_OPTIONS.items():
1306
+ b.add_to_argparse(str(n), parser, '')
1307
+ for n, b in BUILTIN_OPTIONS_PER_MACHINE.items():
1308
+ b.add_to_argparse(str(n), parser, ' (just for host machine)')
1309
+ b.add_to_argparse(str(n.as_build()), parser, ' (just for build machine)')
1310
+ parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option",
1311
+ help='Set the value of an option, can be used several times to set multiple options.')
1312
+
1313
+ def create_options_dict(options: T.List[str], subproject: str = '') -> T.Dict[OptionKey, str]:
1314
+ result: T.OrderedDict[OptionKey, str] = OrderedDict()
1315
+ for o in options:
1316
+ try:
1317
+ (key, value) = o.split('=', 1)
1318
+ except ValueError:
1319
+ raise MesonException(f'Option {o!r} must have a value separated by equals sign.')
1320
+ k = OptionKey.from_string(key)
1321
+ if subproject:
1322
+ k = k.evolve(subproject=subproject)
1323
+ result[k] = value
1324
+ return result
1325
+
1326
+ def parse_cmd_line_options(args: SharedCMDOptions) -> None:
1327
+ args.cmd_line_options = create_options_dict(args.projectoptions)
1328
+
1329
+ # Merge builtin options set with --option into the dict.
1330
+ for key in chain(
1331
+ BUILTIN_OPTIONS.keys(),
1332
+ (k.as_build() for k in BUILTIN_OPTIONS_PER_MACHINE.keys()),
1333
+ BUILTIN_OPTIONS_PER_MACHINE.keys(),
1334
+ ):
1335
+ name = str(key)
1336
+ value = getattr(args, name, None)
1337
+ if value is not None:
1338
+ if key in args.cmd_line_options:
1339
+ cmdline_name = BuiltinOption.argparse_name_to_arg(name)
1340
+ raise MesonException(
1341
+ f'Got argument {name} as both -D{name} and {cmdline_name}. Pick one.')
1342
+ args.cmd_line_options[key] = value
1343
+ delattr(args, name)
1344
+
1345
+
1346
+ _U = T.TypeVar('_U', bound=UserOption[_T])
1347
+
1348
+ class BuiltinOption(T.Generic[_T, _U]):
1349
+
1350
+ """Class for a builtin option type.
1351
+
1352
+ There are some cases that are not fully supported yet.
1353
+ """
1354
+
1355
+ def __init__(self, opt_type: T.Type[_U], description: str, default: T.Any, yielding: bool = True, *,
1356
+ choices: T.Any = None, readonly: bool = False):
1357
+ self.opt_type = opt_type
1358
+ self.description = description
1359
+ self.default = default
1360
+ self.choices = choices
1361
+ self.yielding = yielding
1362
+ self.readonly = readonly
1363
+
1364
+ def init_option(self, name: 'OptionKey', value: T.Optional[T.Any], prefix: str) -> _U:
1365
+ """Create an instance of opt_type and return it."""
1366
+ if value is None:
1367
+ value = self.prefixed_default(name, prefix)
1368
+ keywords = {'yielding': self.yielding, 'value': value}
1369
+ if self.choices:
1370
+ keywords['choices'] = self.choices
1371
+ o = self.opt_type(name.name, self.description, **keywords)
1372
+ o.readonly = self.readonly
1373
+ return o
1374
+
1375
+ def _argparse_action(self) -> T.Optional[str]:
1376
+ # If the type is a boolean, the presence of the argument in --foo form
1377
+ # is to enable it. Disabling happens by using -Dfoo=false, which is
1378
+ # parsed under `args.projectoptions` and does not hit this codepath.
1379
+ if isinstance(self.default, bool):
1380
+ return 'store_true'
1381
+ return None
1382
+
1383
+ def _argparse_choices(self) -> T.Any:
1384
+ if self.opt_type is UserBooleanOption:
1385
+ return [True, False]
1386
+ elif self.opt_type is UserFeatureOption:
1387
+ return UserFeatureOption.static_choices
1388
+ return self.choices
1389
+
1390
+ @staticmethod
1391
+ def argparse_name_to_arg(name: str) -> str:
1392
+ if name == 'warning_level':
1393
+ return '--warnlevel'
1394
+ else:
1395
+ return '--' + name.replace('_', '-')
1396
+
1397
+ def prefixed_default(self, name: 'OptionKey', prefix: str = '') -> T.Any:
1398
+ if self.opt_type in [UserComboOption, UserIntegerOption]:
1399
+ return self.default
1400
+ try:
1401
+ return BUILTIN_DIR_NOPREFIX_OPTIONS[name][prefix]
1402
+ except KeyError:
1403
+ pass
1404
+ return self.default
1405
+
1406
+ def add_to_argparse(self, name: str, parser: argparse.ArgumentParser, help_suffix: str) -> None:
1407
+ kwargs = OrderedDict()
1408
+
1409
+ c = self._argparse_choices()
1410
+ b = self._argparse_action()
1411
+ h = self.description
1412
+ if not b:
1413
+ h = '{} (default: {}).'.format(h.rstrip('.'), self.prefixed_default(name))
1414
+ else:
1415
+ kwargs['action'] = b
1416
+ if c and not b:
1417
+ kwargs['choices'] = c
1418
+ kwargs['default'] = argparse.SUPPRESS
1419
+ kwargs['dest'] = name
1420
+
1421
+ cmdline_name = self.argparse_name_to_arg(name)
1422
+ parser.add_argument(cmdline_name, help=h + help_suffix, **kwargs)
1423
+
1424
+
1425
+ # Update `docs/markdown/Builtin-options.md` after changing the options below
1426
+ # Also update mesonlib._BUILTIN_NAMES. See the comment there for why this is required.
1427
+ # Please also update completion scripts in $MESONSRC/data/shell-completions/
1428
+ BUILTIN_DIR_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([
1429
+ (OptionKey('prefix'), BuiltinOption(UserStringOption, 'Installation prefix', default_prefix())),
1430
+ (OptionKey('bindir'), BuiltinOption(UserStringOption, 'Executable directory', 'bin')),
1431
+ (OptionKey('datadir'), BuiltinOption(UserStringOption, 'Data file directory', default_datadir())),
1432
+ (OptionKey('includedir'), BuiltinOption(UserStringOption, 'Header file directory', default_includedir())),
1433
+ (OptionKey('infodir'), BuiltinOption(UserStringOption, 'Info page directory', default_infodir())),
1434
+ (OptionKey('libdir'), BuiltinOption(UserStringOption, 'Library directory', default_libdir())),
1435
+ (OptionKey('licensedir'), BuiltinOption(UserStringOption, 'Licenses directory', '')),
1436
+ (OptionKey('libexecdir'), BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir())),
1437
+ (OptionKey('localedir'), BuiltinOption(UserStringOption, 'Locale data directory', default_localedir())),
1438
+ (OptionKey('localstatedir'), BuiltinOption(UserStringOption, 'Localstate data directory', 'var')),
1439
+ (OptionKey('mandir'), BuiltinOption(UserStringOption, 'Manual page directory', default_mandir())),
1440
+ (OptionKey('sbindir'), BuiltinOption(UserStringOption, 'System executable directory', default_sbindir())),
1441
+ (OptionKey('sharedstatedir'), BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com')),
1442
+ (OptionKey('sysconfdir'), BuiltinOption(UserStringOption, 'Sysconf data directory', default_sysconfdir())),
1443
+ ])
1444
+
1445
+ BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([
1446
+ (OptionKey('auto_features'), BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto')),
1447
+ (OptionKey('backend'), BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist,
1448
+ readonly=True)),
1449
+ (OptionKey('genvslite'),
1450
+ BuiltinOption(
1451
+ UserComboOption,
1452
+ 'Setup multiple buildtype-suffixed ninja-backend build directories, '
1453
+ 'and a [builddir]_vs containing a Visual Studio meta-backend with multiple configurations that calls into them',
1454
+ 'vs2022',
1455
+ choices=genvslitelist)
1456
+ ),
1457
+ (OptionKey('buildtype'), BuiltinOption(UserComboOption, 'Build type to use', 'debug',
1458
+ choices=buildtypelist)),
1459
+ (OptionKey('debug'), BuiltinOption(UserBooleanOption, 'Enable debug symbols and other information', True)),
1460
+ (OptionKey('default_library'), BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both'],
1461
+ yielding=False)),
1462
+ (OptionKey('errorlogs'), BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True)),
1463
+ (OptionKey('install_umask'), BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022')),
1464
+ (OptionKey('layout'), BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat'])),
1465
+ (OptionKey('optimization'), BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['plain', '0', 'g', '1', '2', '3', 's'])),
1466
+ (OptionKey('prefer_static'), BuiltinOption(UserBooleanOption, 'Whether to try static linking before shared linking', False)),
1467
+ (OptionKey('stdsplit'), BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True)),
1468
+ (OptionKey('strip'), BuiltinOption(UserBooleanOption, 'Strip targets on install', False)),
1469
+ (OptionKey('unity'), BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects'])),
1470
+ (OptionKey('unity_size'), BuiltinOption(UserIntegerOption, 'Unity block size', (2, None, 4))),
1471
+ (OptionKey('warning_level'), BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3', 'everything'], yielding=False)),
1472
+ (OptionKey('werror'), BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False, yielding=False)),
1473
+ (OptionKey('wrap_mode'), BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback', 'nopromote'])),
1474
+ (OptionKey('force_fallback_for'), BuiltinOption(UserArrayOption, 'Force fallback for those subprojects', [])),
1475
+ (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)),
1476
+
1477
+ # Pkgconfig module
1478
+ (OptionKey('relocatable', module='pkgconfig'),
1479
+ BuiltinOption(UserBooleanOption, 'Generate pkgconfig files as relocatable', False)),
1480
+
1481
+ # Python module
1482
+ (OptionKey('bytecompile', module='python'),
1483
+ BuiltinOption(UserIntegerOption, 'Whether to compile bytecode', (-1, 2, 0))),
1484
+ (OptionKey('install_env', module='python'),
1485
+ BuiltinOption(UserComboOption, 'Which python environment to install to', 'prefix', choices=['auto', 'prefix', 'system', 'venv'])),
1486
+ (OptionKey('platlibdir', module='python'),
1487
+ BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')),
1488
+ (OptionKey('purelibdir', module='python'),
1489
+ BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')),
1490
+ (OptionKey('allow_limited_api', module='python'),
1491
+ BuiltinOption(UserBooleanOption, 'Whether to allow use of the Python Limited API', True)),
1492
+ ])
1493
+
1494
+ BUILTIN_OPTIONS = OrderedDict(chain(BUILTIN_DIR_OPTIONS.items(), BUILTIN_CORE_OPTIONS.items()))
1495
+
1496
+ BUILTIN_OPTIONS_PER_MACHINE: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([
1497
+ (OptionKey('pkg_config_path'), BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [])),
1498
+ (OptionKey('cmake_prefix_path'), BuiltinOption(UserArrayOption, 'List of additional prefixes for cmake to search', [])),
1499
+ ])
1500
+
1501
+ # Special prefix-dependent defaults for installation directories that reside in
1502
+ # a path outside of the prefix in FHS and common usage.
1503
+ BUILTIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = {
1504
+ OptionKey('sysconfdir'): {'/usr': '/etc'},
1505
+ OptionKey('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'},
1506
+ OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'},
1507
+ OptionKey('platlibdir', module='python'): {},
1508
+ OptionKey('purelibdir', module='python'): {},
1509
+ }
1510
+
1511
+ FORBIDDEN_TARGET_NAMES = frozenset({
1512
+ 'clean',
1513
+ 'clean-ctlist',
1514
+ 'clean-gcno',
1515
+ 'clean-gcda',
1516
+ 'coverage',
1517
+ 'coverage-text',
1518
+ 'coverage-xml',
1519
+ 'coverage-html',
1520
+ 'phony',
1521
+ 'PHONY',
1522
+ 'all',
1523
+ 'test',
1524
+ 'benchmark',
1525
+ 'install',
1526
+ 'uninstall',
1527
+ 'build.ninja',
1528
+ 'scan-build',
1529
+ 'reconfigure',
1530
+ 'dist',
1531
+ 'distcheck',
1532
+ })