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,1330 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2012-2023 The Meson development team
3
+
4
+ from __future__ import annotations
5
+
6
+
7
+ """Mixin classes to be shared between C and C++ compilers.
8
+
9
+ Without this we'll end up with awful diamond inheritance problems. The goal
10
+ of this is to have mixin's, which are classes that are designed *not* to be
11
+ standalone, they only work through inheritance.
12
+ """
13
+
14
+ import collections
15
+ import functools
16
+ import glob
17
+ import itertools
18
+ import os
19
+ import re
20
+ import subprocess
21
+ import copy
22
+ import typing as T
23
+ from pathlib import Path
24
+
25
+ from ... import arglist
26
+ from ... import mesonlib
27
+ from ... import mlog
28
+ from ...linkers.linkers import GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker
29
+ from ...mesonlib import LibType, OptionKey
30
+ from .. import compilers
31
+ from ..compilers import CompileCheckMode
32
+ from .visualstudio import VisualStudioLikeCompiler
33
+
34
+ if T.TYPE_CHECKING:
35
+ from ...dependencies import Dependency
36
+ from ..._typing import ImmutableListProtocol
37
+ from ...environment import Environment
38
+ from ...compilers.compilers import Compiler
39
+ else:
40
+ # This is a bit clever, for mypy we pretend that these mixins descend from
41
+ # Compiler, so we get all of the methods and attributes defined for us, but
42
+ # for runtime we make them descend from object (which all classes normally
43
+ # do). This gives up DRYer type checking, with no runtime impact
44
+ Compiler = object
45
+
46
+ GROUP_FLAGS = re.compile(r'''^(?!-Wl,) .*\.so (?:\.[0-9]+)? (?:\.[0-9]+)? (?:\.[0-9]+)?$ |
47
+ ^(?:-Wl,)?-l |
48
+ \.a$''', re.X)
49
+
50
+ class CLikeCompilerArgs(arglist.CompilerArgs):
51
+ prepend_prefixes = ('-I', '-L')
52
+ dedup2_prefixes = ('-I', '-isystem', '-L', '-D', '-U')
53
+
54
+ # NOTE: not thorough. A list of potential corner cases can be found in
55
+ # https://github.com/mesonbuild/meson/pull/4593#pullrequestreview-182016038
56
+ dedup1_prefixes = ('-l', '-Wl,-l', '-Wl,--export-dynamic')
57
+ dedup1_suffixes = ('.lib', '.dll', '.so', '.dylib', '.a')
58
+ dedup1_args = ('-c', '-S', '-E', '-pipe', '-pthread')
59
+
60
+ def to_native(self, copy: bool = False) -> T.List[str]:
61
+ # This seems to be allowed, but could never work?
62
+ assert isinstance(self.compiler, compilers.Compiler), 'How did you get here'
63
+
64
+ # Check if we need to add --start/end-group for circular dependencies
65
+ # between static libraries, and for recursively searching for symbols
66
+ # needed by static libraries that are provided by object files or
67
+ # shared libraries.
68
+ self.flush_pre_post()
69
+ if copy:
70
+ new = self.copy()
71
+ else:
72
+ new = self
73
+ # This covers all ld.bfd, ld.gold, ld.gold, and xild on Linux, which
74
+ # all act like (or are) gnu ld
75
+ # TODO: this could probably be added to the DynamicLinker instead
76
+ if isinstance(self.compiler.linker, (GnuLikeDynamicLinkerMixin, SolarisDynamicLinker, CompCertDynamicLinker)):
77
+ group_start = -1
78
+ group_end = -1
79
+ for i, each in enumerate(new):
80
+ if not GROUP_FLAGS.search(each):
81
+ continue
82
+ group_end = i
83
+ if group_start < 0:
84
+ # First occurrence of a library
85
+ group_start = i
86
+ # Only add groups if there are multiple libraries.
87
+ if group_end > group_start >= 0:
88
+ # Last occurrence of a library
89
+ new.insert(group_end + 1, '-Wl,--end-group')
90
+ new.insert(group_start, '-Wl,--start-group')
91
+ # Remove system/default include paths added with -isystem
92
+ default_dirs = self.compiler.get_default_include_dirs()
93
+ if default_dirs:
94
+ real_default_dirs = [self._cached_realpath(i) for i in default_dirs]
95
+ bad_idx_list: T.List[int] = []
96
+ for i, each in enumerate(new):
97
+ if not each.startswith('-isystem'):
98
+ continue
99
+
100
+ # Remove the -isystem and the path if the path is a default path
101
+ if (each == '-isystem' and
102
+ i < (len(new) - 1) and
103
+ self._cached_realpath(new[i + 1]) in real_default_dirs):
104
+ bad_idx_list += [i, i + 1]
105
+ elif each.startswith('-isystem=') and self._cached_realpath(each[9:]) in real_default_dirs:
106
+ bad_idx_list += [i]
107
+ elif self._cached_realpath(each[8:]) in real_default_dirs:
108
+ bad_idx_list += [i]
109
+ for i in reversed(bad_idx_list):
110
+ new.pop(i)
111
+ return self.compiler.unix_args_to_native(new._container)
112
+
113
+ @staticmethod
114
+ @functools.lru_cache(maxsize=None)
115
+ def _cached_realpath(arg: str) -> str:
116
+ return os.path.realpath(arg)
117
+
118
+ def __repr__(self) -> str:
119
+ self.flush_pre_post()
120
+ return f'CLikeCompilerArgs({self.compiler!r}, {self._container!r})'
121
+
122
+
123
+ class CLikeCompiler(Compiler):
124
+
125
+ """Shared bits for the C and CPP Compilers."""
126
+
127
+ if T.TYPE_CHECKING:
128
+ warn_args: T.Dict[str, T.List[str]] = {}
129
+
130
+ # TODO: Replace this manual cache with functools.lru_cache
131
+ find_library_cache: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], str, LibType], T.Optional[T.List[str]]] = {}
132
+ find_framework_cache: T.Dict[T.Tuple[T.Tuple[str, ...], str, T.Tuple[str, ...], bool], T.Optional[T.List[str]]] = {}
133
+ internal_libs = arglist.UNIXY_COMPILER_INTERNAL_LIBS
134
+
135
+ def __init__(self) -> None:
136
+ # If a child ObjC or CPP class has already set it, don't set it ourselves
137
+ self.can_compile_suffixes.add('h')
138
+ # Lazy initialized in get_preprocessor()
139
+ self.preprocessor: T.Optional[Compiler] = None
140
+
141
+ def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CLikeCompilerArgs:
142
+ # This is correct, mypy just doesn't understand co-operative inheritance
143
+ return CLikeCompilerArgs(self, args)
144
+
145
+ def needs_static_linker(self) -> bool:
146
+ return True # When compiling static libraries, so yes.
147
+
148
+ def get_always_args(self) -> T.List[str]:
149
+ '''
150
+ Args that are always-on for all C compilers other than MSVC
151
+ '''
152
+ return self.get_largefile_args()
153
+
154
+ def get_no_stdinc_args(self) -> T.List[str]:
155
+ return ['-nostdinc']
156
+
157
+ def get_no_stdlib_link_args(self) -> T.List[str]:
158
+ return ['-nostdlib']
159
+
160
+ def get_warn_args(self, level: str) -> T.List[str]:
161
+ # TODO: this should be an enum
162
+ return self.warn_args[level]
163
+
164
+ def get_depfile_suffix(self) -> str:
165
+ return 'd'
166
+
167
+ def get_preprocess_only_args(self) -> T.List[str]:
168
+ return ['-E', '-P']
169
+
170
+ def get_compile_only_args(self) -> T.List[str]:
171
+ return ['-c']
172
+
173
+ def get_no_optimization_args(self) -> T.List[str]:
174
+ return ['-O0']
175
+
176
+ def get_output_args(self, outputname: str) -> T.List[str]:
177
+ return ['-o', outputname]
178
+
179
+ def get_werror_args(self) -> T.List[str]:
180
+ return ['-Werror']
181
+
182
+ def get_include_args(self, path: str, is_system: bool) -> T.List[str]:
183
+ if path == '':
184
+ path = '.'
185
+ if is_system:
186
+ return ['-isystem', path]
187
+ return ['-I' + path]
188
+
189
+ def get_compiler_dirs(self, env: 'Environment', name: str) -> T.List[str]:
190
+ '''
191
+ Get dirs from the compiler, either `libraries:` or `programs:`
192
+ '''
193
+ return []
194
+
195
+ @functools.lru_cache()
196
+ def _get_library_dirs(self, env: 'Environment',
197
+ elf_class: T.Optional[int] = None) -> 'ImmutableListProtocol[str]':
198
+ # TODO: replace elf_class with enum
199
+ dirs = self.get_compiler_dirs(env, 'libraries')
200
+ if elf_class is None or elf_class == 0:
201
+ return dirs
202
+
203
+ # if we do have an elf class for 32-bit or 64-bit, we want to check that
204
+ # the directory in question contains libraries of the appropriate class. Since
205
+ # system directories aren't mixed, we only need to check one file for each
206
+ # directory and go by that. If we can't check the file for some reason, assume
207
+ # the compiler knows what it's doing, and accept the directory anyway.
208
+ retval: T.List[str] = []
209
+ for d in dirs:
210
+ files = [f for f in os.listdir(d) if f.endswith('.so') and os.path.isfile(os.path.join(d, f))]
211
+ # if no files, accept directory and move on
212
+ if not files:
213
+ retval.append(d)
214
+ continue
215
+
216
+ for f in files:
217
+ file_to_check = os.path.join(d, f)
218
+ try:
219
+ with open(file_to_check, 'rb') as fd:
220
+ header = fd.read(5)
221
+ # if file is not an ELF file, it's weird, but accept dir
222
+ # if it is elf, and the class matches, accept dir
223
+ if header[1:4] != b'ELF' or int(header[4]) == elf_class:
224
+ retval.append(d)
225
+ # at this point, it's an ELF file which doesn't match the
226
+ # appropriate elf_class, so skip this one
227
+ # stop scanning after the first successful read
228
+ break
229
+ except OSError:
230
+ # Skip the file if we can't read it
231
+ pass
232
+
233
+ return retval
234
+
235
+ def get_library_dirs(self, env: 'Environment',
236
+ elf_class: T.Optional[int] = None) -> T.List[str]:
237
+ """Wrap the lru_cache so that we return a new copy and don't allow
238
+ mutation of the cached value.
239
+ """
240
+ return self._get_library_dirs(env, elf_class).copy()
241
+
242
+ @functools.lru_cache()
243
+ def _get_program_dirs(self, env: 'Environment') -> 'ImmutableListProtocol[str]':
244
+ '''
245
+ Programs used by the compiler. Also where toolchain DLLs such as
246
+ libstdc++-6.dll are found with MinGW.
247
+ '''
248
+ return self.get_compiler_dirs(env, 'programs')
249
+
250
+ def get_program_dirs(self, env: 'Environment') -> T.List[str]:
251
+ return self._get_program_dirs(env).copy()
252
+
253
+ def get_pic_args(self) -> T.List[str]:
254
+ return ['-fPIC']
255
+
256
+ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
257
+ return ['-include', os.path.basename(header)]
258
+
259
+ def get_pch_name(self, name: str) -> str:
260
+ return os.path.basename(name) + '.' + self.get_pch_suffix()
261
+
262
+ def get_default_include_dirs(self) -> T.List[str]:
263
+ return []
264
+
265
+ def gen_export_dynamic_link_args(self, env: 'Environment') -> T.List[str]:
266
+ return self.linker.export_dynamic_args(env)
267
+
268
+ def gen_import_library_args(self, implibname: str) -> T.List[str]:
269
+ return self.linker.import_library_args(implibname)
270
+
271
+ def _sanity_check_impl(self, work_dir: str, environment: 'Environment',
272
+ sname: str, code: str) -> None:
273
+ mlog.debug('Sanity testing ' + self.get_display_language() + ' compiler:', mesonlib.join_args(self.exelist))
274
+ mlog.debug(f'Is cross compiler: {self.is_cross!s}.')
275
+
276
+ source_name = os.path.join(work_dir, sname)
277
+ binname = sname.rsplit('.', 1)[0]
278
+ mode = CompileCheckMode.LINK
279
+ if self.is_cross:
280
+ binname += '_cross'
281
+ if environment.need_exe_wrapper(self.for_machine) and not environment.has_exe_wrapper():
282
+ # Linking cross built C/C++ apps is painful. You can't really
283
+ # tell if you should use -nostdlib or not and for example
284
+ # on OSX the compiler binary is the same but you need
285
+ # a ton of compiler flags to differentiate between
286
+ # arm and x86_64. So just compile.
287
+ mode = CompileCheckMode.COMPILE
288
+ cargs, largs = self._get_basic_compiler_args(environment, mode)
289
+ extra_flags = cargs + self.linker_to_compiler_args(largs)
290
+
291
+ # Is a valid executable output for all toolchains and platforms
292
+ binname += '.exe'
293
+ # Write binary check source
294
+ binary_name = os.path.join(work_dir, binname)
295
+ with open(source_name, 'w', encoding='utf-8') as ofile:
296
+ ofile.write(code)
297
+ # Compile sanity check
298
+ # NOTE: extra_flags must be added at the end. On MSVC, it might contain a '/link' argument
299
+ # after which all further arguments will be passed directly to the linker
300
+ cmdlist = self.exelist + [sname] + self.get_output_args(binname) + extra_flags
301
+ pc, stdo, stde = mesonlib.Popen_safe(cmdlist, cwd=work_dir)
302
+ mlog.debug('Sanity check compiler command line:', mesonlib.join_args(cmdlist))
303
+ mlog.debug('Sanity check compile stdout:')
304
+ mlog.debug(stdo)
305
+ mlog.debug('-----\nSanity check compile stderr:')
306
+ mlog.debug(stde)
307
+ mlog.debug('-----')
308
+ if pc.returncode != 0:
309
+ raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.')
310
+ # Run sanity check
311
+ if environment.need_exe_wrapper(self.for_machine):
312
+ if not environment.has_exe_wrapper():
313
+ # Can't check if the binaries run so we have to assume they do
314
+ return
315
+ cmdlist = environment.exe_wrapper.get_command() + [binary_name]
316
+ else:
317
+ cmdlist = [binary_name]
318
+ mlog.debug('Running test binary command: ', mesonlib.join_args(cmdlist))
319
+ try:
320
+ # fortran code writes to stdout
321
+ pe = subprocess.run(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
322
+ except Exception as e:
323
+ raise mesonlib.EnvironmentException(f'Could not invoke sanity test executable: {e!s}.')
324
+ if pe.returncode != 0:
325
+ raise mesonlib.EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.')
326
+
327
+ def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
328
+ code = 'int main(void) { int class=0; return class; }\n'
329
+ return self._sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
330
+
331
+ def check_header(self, hname: str, prefix: str, env: 'Environment', *,
332
+ extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None,
333
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
334
+ code = f'''{prefix}
335
+ #include <{hname}>\n'''
336
+ return self.compiles(code, env, extra_args=extra_args,
337
+ dependencies=dependencies)
338
+
339
+ def has_header(self, hname: str, prefix: str, env: 'Environment', *,
340
+ extra_args: T.Union[None, T.List[str], T.Callable[['CompileCheckMode'], T.List[str]]] = None,
341
+ dependencies: T.Optional[T.List['Dependency']] = None,
342
+ disable_cache: bool = False) -> T.Tuple[bool, bool]:
343
+ code = f'''{prefix}
344
+ #ifdef __has_include
345
+ #if !__has_include("{hname}")
346
+ #error "Header '{hname}' could not be found"
347
+ #endif
348
+ #else
349
+ #include <{hname}>
350
+ #endif\n'''
351
+ return self.compiles(code, env, extra_args=extra_args,
352
+ dependencies=dependencies, mode=CompileCheckMode.PREPROCESS, disable_cache=disable_cache)
353
+
354
+ def has_header_symbol(self, hname: str, symbol: str, prefix: str,
355
+ env: 'Environment', *,
356
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
357
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
358
+ t = f'''{prefix}
359
+ #include <{hname}>
360
+ int main(void) {{
361
+ /* If it's not defined as a macro, try to use as a symbol */
362
+ #ifndef {symbol}
363
+ {symbol};
364
+ #endif
365
+ return 0;
366
+ }}\n'''
367
+ return self.compiles(t, env, extra_args=extra_args,
368
+ dependencies=dependencies)
369
+
370
+ def _get_basic_compiler_args(self, env: 'Environment', mode: CompileCheckMode) -> T.Tuple[T.List[str], T.List[str]]:
371
+ cargs: T.List[str] = []
372
+ largs: T.List[str] = []
373
+ if mode is CompileCheckMode.LINK:
374
+ # Sometimes we need to manually select the CRT to use with MSVC.
375
+ # One example is when trying to do a compiler check that involves
376
+ # linking with static libraries since MSVC won't select a CRT for
377
+ # us in that case and will error out asking us to pick one.
378
+ try:
379
+ crt_val = env.coredata.options[OptionKey('b_vscrt')].value
380
+ buildtype = env.coredata.options[OptionKey('buildtype')].value
381
+ cargs += self.get_crt_compile_args(crt_val, buildtype)
382
+ except (KeyError, AttributeError):
383
+ pass
384
+
385
+ # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS and CPPFLAGS from the env
386
+ sys_args = env.coredata.get_external_args(self.for_machine, self.language)
387
+ if isinstance(sys_args, str):
388
+ sys_args = [sys_args]
389
+ # Apparently it is a thing to inject linker flags both
390
+ # via CFLAGS _and_ LDFLAGS, even though the former are
391
+ # also used during linking. These flags can break
392
+ # argument checks. Thanks, Autotools.
393
+ cleaned_sys_args = self.remove_linkerlike_args(sys_args)
394
+ cargs += cleaned_sys_args
395
+
396
+ if mode is CompileCheckMode.LINK:
397
+ ld_value = env.lookup_binary_entry(self.for_machine, self.language + '_ld')
398
+ if ld_value is not None:
399
+ largs += self.use_linker_args(ld_value[0], self.version)
400
+
401
+ # Add LDFLAGS from the env
402
+ sys_ld_args = env.coredata.get_external_link_args(self.for_machine, self.language)
403
+ # CFLAGS and CXXFLAGS go to both linking and compiling, but we want them
404
+ # to only appear on the command line once. Remove dupes.
405
+ largs += [x for x in sys_ld_args if x not in sys_args]
406
+
407
+ cargs += self.get_compiler_args_for_mode(mode)
408
+ return cargs, largs
409
+
410
+ def build_wrapper_args(self, env: 'Environment',
411
+ extra_args: T.Union[None, arglist.CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]],
412
+ dependencies: T.Optional[T.List['Dependency']],
413
+ mode: CompileCheckMode = CompileCheckMode.COMPILE) -> arglist.CompilerArgs:
414
+ # TODO: the caller should handle the listing of these arguments
415
+ if extra_args is None:
416
+ extra_args = []
417
+ else:
418
+ # TODO: we want to do this in the caller
419
+ extra_args = mesonlib.listify(extra_args)
420
+ extra_args = mesonlib.listify([e(mode.value) if callable(e) else e for e in extra_args])
421
+
422
+ if dependencies is None:
423
+ dependencies = []
424
+ elif not isinstance(dependencies, collections.abc.Iterable):
425
+ # TODO: we want to ensure the front end does the listifing here
426
+ dependencies = [dependencies]
427
+ # Collect compiler arguments
428
+ cargs: arglist.CompilerArgs = self.compiler_args()
429
+ largs: T.List[str] = []
430
+ for d in dependencies:
431
+ # Add compile flags needed by dependencies
432
+ cargs += d.get_compile_args()
433
+ system_incdir = d.get_include_type() == 'system'
434
+ for i in d.get_include_dirs():
435
+ for idir in i.to_string_list(env.get_source_dir(), env.get_build_dir()):
436
+ cargs.extend(self.get_include_args(idir, system_incdir))
437
+ if mode is CompileCheckMode.LINK:
438
+ # Add link flags needed to find dependencies
439
+ largs += d.get_link_args()
440
+
441
+ ca, la = self._get_basic_compiler_args(env, mode)
442
+ cargs += ca
443
+ largs += la
444
+
445
+ cargs += self.get_compiler_check_args(mode)
446
+
447
+ # on MSVC compiler and linker flags must be separated by the "/link" argument
448
+ # at this point, the '/link' argument may already be part of extra_args, otherwise, it is added here
449
+ if self.linker_to_compiler_args([]) == ['/link'] and largs != [] and '/link' not in extra_args:
450
+ extra_args += ['/link']
451
+
452
+ args = cargs + extra_args + largs
453
+ return args
454
+
455
+ def _compile_int(self, expression: str, prefix: str, env: 'Environment',
456
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]],
457
+ dependencies: T.Optional[T.List['Dependency']]) -> bool:
458
+ t = f'''{prefix}
459
+ #include <stddef.h>
460
+ int main(void) {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}\n'''
461
+ return self.compiles(t, env, extra_args=extra_args,
462
+ dependencies=dependencies)[0]
463
+
464
+ def cross_compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int],
465
+ guess: T.Optional[int], prefix: str, env: 'Environment',
466
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
467
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
468
+ # Try user's guess first
469
+ if isinstance(guess, int):
470
+ if self._compile_int(f'{expression} == {guess}', prefix, env, extra_args, dependencies):
471
+ return guess
472
+
473
+ # If no bounds are given, compute them in the limit of int32
474
+ maxint = 0x7fffffff
475
+ minint = -0x80000000
476
+ if not isinstance(low, int) or not isinstance(high, int):
477
+ if self._compile_int(f'{expression} >= 0', prefix, env, extra_args, dependencies):
478
+ low = cur = 0
479
+ while self._compile_int(f'{expression} > {cur}', prefix, env, extra_args, dependencies):
480
+ low = cur + 1
481
+ if low > maxint:
482
+ raise mesonlib.EnvironmentException('Cross-compile check overflowed')
483
+ cur = min(cur * 2 + 1, maxint)
484
+ high = cur
485
+ else:
486
+ high = cur = -1
487
+ while self._compile_int(f'{expression} < {cur}', prefix, env, extra_args, dependencies):
488
+ high = cur - 1
489
+ if high < minint:
490
+ raise mesonlib.EnvironmentException('Cross-compile check overflowed')
491
+ cur = max(cur * 2, minint)
492
+ low = cur
493
+ else:
494
+ # Sanity check limits given by user
495
+ if high < low:
496
+ raise mesonlib.EnvironmentException('high limit smaller than low limit')
497
+ condition = f'{expression} <= {high} && {expression} >= {low}'
498
+ if not self._compile_int(condition, prefix, env, extra_args, dependencies):
499
+ raise mesonlib.EnvironmentException('Value out of given range')
500
+
501
+ # Binary search
502
+ while low != high:
503
+ cur = low + int((high - low) / 2)
504
+ if self._compile_int(f'{expression} <= {cur}', prefix, env, extra_args, dependencies):
505
+ high = cur
506
+ else:
507
+ low = cur + 1
508
+
509
+ return low
510
+
511
+ def compute_int(self, expression: str, low: T.Optional[int], high: T.Optional[int],
512
+ guess: T.Optional[int], prefix: str, env: 'Environment', *,
513
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]],
514
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
515
+ if extra_args is None:
516
+ extra_args = []
517
+ if self.is_cross:
518
+ return self.cross_compute_int(expression, low, high, guess, prefix, env, extra_args, dependencies)
519
+ t = f'''{prefix}
520
+ #include<stddef.h>
521
+ #include<stdio.h>
522
+ int main(void) {{
523
+ printf("%ld\\n", (long)({expression}));
524
+ return 0;
525
+ }}'''
526
+ res = self.run(t, env, extra_args=extra_args,
527
+ dependencies=dependencies)
528
+ if not res.compiled:
529
+ return -1
530
+ if res.returncode != 0:
531
+ raise mesonlib.EnvironmentException('Could not run compute_int test binary.')
532
+ return int(res.stdout)
533
+
534
+ def cross_sizeof(self, typename: str, prefix: str, env: 'Environment', *,
535
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
536
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
537
+ if extra_args is None:
538
+ extra_args = []
539
+ t = f'''{prefix}
540
+ #include <stddef.h>
541
+ int main(void) {{
542
+ {typename} something;
543
+ return 0;
544
+ }}\n'''
545
+ if not self.compiles(t, env, extra_args=extra_args,
546
+ dependencies=dependencies)[0]:
547
+ return -1
548
+ return self.cross_compute_int(f'sizeof({typename})', None, None, None, prefix, env, extra_args, dependencies)
549
+
550
+ def sizeof(self, typename: str, prefix: str, env: 'Environment', *,
551
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
552
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]:
553
+ if extra_args is None:
554
+ extra_args = []
555
+ if self.is_cross:
556
+ r = self.cross_sizeof(typename, prefix, env, extra_args=extra_args,
557
+ dependencies=dependencies)
558
+ return r, False
559
+ t = f'''{prefix}
560
+ #include<stddef.h>
561
+ #include<stdio.h>
562
+ int main(void) {{
563
+ printf("%ld\\n", (long)(sizeof({typename})));
564
+ return 0;
565
+ }}'''
566
+ res = self.cached_run(t, env, extra_args=extra_args,
567
+ dependencies=dependencies)
568
+ if not res.compiled:
569
+ return -1, False
570
+ if res.returncode != 0:
571
+ raise mesonlib.EnvironmentException('Could not run sizeof test binary.')
572
+ return int(res.stdout), res.cached
573
+
574
+ def cross_alignment(self, typename: str, prefix: str, env: 'Environment', *,
575
+ extra_args: T.Optional[T.List[str]] = None,
576
+ dependencies: T.Optional[T.List['Dependency']] = None) -> int:
577
+ if extra_args is None:
578
+ extra_args = []
579
+ t = f'''{prefix}
580
+ #include <stddef.h>
581
+ int main(void) {{
582
+ {typename} something;
583
+ return 0;
584
+ }}\n'''
585
+ if not self.compiles(t, env, extra_args=extra_args,
586
+ dependencies=dependencies)[0]:
587
+ return -1
588
+ t = f'''{prefix}
589
+ #include <stddef.h>
590
+ struct tmp {{
591
+ char c;
592
+ {typename} target;
593
+ }};'''
594
+ return self.cross_compute_int('offsetof(struct tmp, target)', None, None, None, t, env, extra_args, dependencies)
595
+
596
+ def alignment(self, typename: str, prefix: str, env: 'Environment', *,
597
+ extra_args: T.Optional[T.List[str]] = None,
598
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[int, bool]:
599
+ if extra_args is None:
600
+ extra_args = []
601
+ if self.is_cross:
602
+ r = self.cross_alignment(typename, prefix, env, extra_args=extra_args,
603
+ dependencies=dependencies)
604
+ return r, False
605
+ t = f'''{prefix}
606
+ #include <stdio.h>
607
+ #include <stddef.h>
608
+ struct tmp {{
609
+ char c;
610
+ {typename} target;
611
+ }};
612
+ int main(void) {{
613
+ printf("%d", (int)offsetof(struct tmp, target));
614
+ return 0;
615
+ }}'''
616
+ res = self.cached_run(t, env, extra_args=extra_args,
617
+ dependencies=dependencies)
618
+ if not res.compiled:
619
+ raise mesonlib.EnvironmentException('Could not compile alignment test.')
620
+ if res.returncode != 0:
621
+ raise mesonlib.EnvironmentException('Could not run alignment test binary.')
622
+ align = int(res.stdout)
623
+ if align == 0:
624
+ raise mesonlib.EnvironmentException(f'Could not determine alignment of {typename}. Sorry. You might want to file a bug.')
625
+ return align, res.cached
626
+
627
+ def get_define(self, dname: str, prefix: str, env: 'Environment',
628
+ extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]],
629
+ dependencies: T.Optional[T.List['Dependency']],
630
+ disable_cache: bool = False) -> T.Tuple[str, bool]:
631
+ delim_start = '"MESON_GET_DEFINE_DELIMITER_START"\n'
632
+ delim_end = '\n"MESON_GET_DEFINE_DELIMITER_END"'
633
+ sentinel_undef = '"MESON_GET_DEFINE_UNDEFINED_SENTINEL"'
634
+ code = f'''
635
+ {prefix}
636
+ #ifndef {dname}
637
+ # define {dname} {sentinel_undef}
638
+ #endif
639
+ {delim_start}{dname}{delim_end}'''
640
+ args = self.build_wrapper_args(env, extra_args, dependencies,
641
+ mode=CompileCheckMode.PREPROCESS).to_native()
642
+ func = functools.partial(self.cached_compile, code, env.coredata, extra_args=args, mode=CompileCheckMode.PREPROCESS)
643
+ if disable_cache:
644
+ func = functools.partial(self.compile, code, extra_args=args, mode=CompileCheckMode.PREPROCESS)
645
+ with func() as p:
646
+ cached = p.cached
647
+ if p.returncode != 0:
648
+ raise mesonlib.EnvironmentException(f'Could not get define {dname!r}')
649
+
650
+ # Get the preprocessed value between the delimiters
651
+ star_idx = p.stdout.find(delim_start)
652
+ end_idx = p.stdout.rfind(delim_end)
653
+ if (star_idx == -1) or (end_idx == -1) or (star_idx == end_idx):
654
+ raise mesonlib.MesonBugException('Delimiters not found in preprocessor output.')
655
+ define_value = p.stdout[star_idx + len(delim_start):end_idx]
656
+
657
+ if define_value == sentinel_undef:
658
+ define_value = None
659
+ else:
660
+ # Merge string literals
661
+ define_value = self._concatenate_string_literals(define_value).strip()
662
+
663
+ return define_value, cached
664
+
665
+ def get_return_value(self, fname: str, rtype: str, prefix: str,
666
+ env: 'Environment', extra_args: T.Optional[T.List[str]],
667
+ dependencies: T.Optional[T.List['Dependency']]) -> T.Union[str, int]:
668
+ # TODO: rtype should be an enum.
669
+ # TODO: maybe we can use overload to tell mypy when this will return int vs str?
670
+ if rtype == 'string':
671
+ fmt = '%s'
672
+ cast = '(char*)'
673
+ elif rtype == 'int':
674
+ fmt = '%lli'
675
+ cast = '(long long int)'
676
+ else:
677
+ raise AssertionError(f'BUG: Unknown return type {rtype!r}')
678
+ code = f'''{prefix}
679
+ #include <stdio.h>
680
+ int main(void) {{
681
+ printf ("{fmt}", {cast} {fname}());
682
+ return 0;
683
+ }}'''
684
+ res = self.run(code, env, extra_args=extra_args, dependencies=dependencies)
685
+ if not res.compiled:
686
+ raise mesonlib.EnvironmentException(f'Could not get return value of {fname}()')
687
+ if rtype == 'string':
688
+ return res.stdout
689
+ elif rtype == 'int':
690
+ try:
691
+ return int(res.stdout.strip())
692
+ except ValueError:
693
+ raise mesonlib.EnvironmentException(f'Return value of {fname}() is not an int')
694
+ assert False, 'Unreachable'
695
+
696
+ @staticmethod
697
+ def _no_prototype_templ() -> T.Tuple[str, str]:
698
+ """
699
+ Try to find the function without a prototype from a header by defining
700
+ our own dummy prototype and trying to link with the C library (and
701
+ whatever else the compiler links in by default). This is very similar
702
+ to the check performed by Autoconf for AC_CHECK_FUNCS.
703
+ """
704
+ # Define the symbol to something else since it is defined by the
705
+ # includes or defines listed by the user or by the compiler. This may
706
+ # include, for instance _GNU_SOURCE which must be defined before
707
+ # limits.h, which includes features.h
708
+ # Then, undef the symbol to get rid of it completely.
709
+ head = '''
710
+ #define {func} meson_disable_define_of_{func}
711
+ {prefix}
712
+ #include <limits.h>
713
+ #undef {func}
714
+ '''
715
+ # Override any GCC internal prototype and declare our own definition for
716
+ # the symbol. Use char because that's unlikely to be an actual return
717
+ # value for a function which ensures that we override the definition.
718
+ head += '''
719
+ #ifdef __cplusplus
720
+ extern "C"
721
+ #endif
722
+ char {func} (void);
723
+ '''
724
+ # The actual function call
725
+ main = '''
726
+ int main(void) {{
727
+ return {func} ();
728
+ }}'''
729
+ return head, main
730
+
731
+ @staticmethod
732
+ def _have_prototype_templ() -> T.Tuple[str, str]:
733
+ """
734
+ Returns a head-er and main() call that uses the headers listed by the
735
+ user for the function prototype while checking if a function exists.
736
+ """
737
+ # Add the 'prefix', aka defines, includes, etc that the user provides
738
+ # This may include, for instance _GNU_SOURCE which must be defined
739
+ # before limits.h, which includes features.h
740
+ head = '{prefix}\n#include <limits.h>\n'
741
+ # We don't know what the function takes or returns, so return it as an int.
742
+ # Just taking the address or comparing it to void is not enough because
743
+ # compilers are smart enough to optimize it away. The resulting binary
744
+ # is not run so we don't care what the return value is.
745
+ main = '''\nint main(void) {{
746
+ void *a = (void*) &{func};
747
+ long long b = (long long) a;
748
+ return (int) b;
749
+ }}'''
750
+ return head, main
751
+
752
+ def has_function(self, funcname: str, prefix: str, env: 'Environment', *,
753
+ extra_args: T.Optional[T.List[str]] = None,
754
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
755
+ """Determine if a function exists.
756
+
757
+ First, this function looks for the symbol in the default libraries
758
+ provided by the compiler (stdlib + a few others usually). If that
759
+ fails, it checks if any of the headers specified in the prefix provide
760
+ an implementation of the function, and if that fails, it checks if it's
761
+ implemented as a compiler-builtin.
762
+ """
763
+ if extra_args is None:
764
+ extra_args = []
765
+
766
+ # Short-circuit if the check is already provided by the cross-info file
767
+ varname = 'has function ' + funcname
768
+ varname = varname.replace(' ', '_')
769
+ if self.is_cross:
770
+ val = env.properties.host.get(varname, None)
771
+ if val is not None:
772
+ if isinstance(val, bool):
773
+ return val, False
774
+ raise mesonlib.EnvironmentException(f'Cross variable {varname} is not a boolean.')
775
+
776
+ # TODO: we really need a protocol for this,
777
+ #
778
+ # class StrProto(typing.Protocol):
779
+ # def __str__(self) -> str: ...
780
+ fargs: T.Dict[str, T.Union[str, bool, int]] = {'prefix': prefix, 'func': funcname}
781
+
782
+ # glibc defines functions that are not available on Linux as stubs that
783
+ # fail with ENOSYS (such as e.g. lchmod). In this case we want to fail
784
+ # instead of detecting the stub as a valid symbol.
785
+ # We already included limits.h earlier to ensure that these are defined
786
+ # for stub functions.
787
+ stubs_fail = '''
788
+ #if defined __stub_{func} || defined __stub___{func}
789
+ fail fail fail this function is not going to work
790
+ #endif
791
+ '''
792
+
793
+ # If we have any includes in the prefix supplied by the user, assume
794
+ # that the user wants us to use the symbol prototype defined in those
795
+ # includes. If not, then try to do the Autoconf-style check with
796
+ # a dummy prototype definition of our own.
797
+ # This is needed when the linker determines symbol availability from an
798
+ # SDK based on the prototype in the header provided by the SDK.
799
+ # Ignoring this prototype would result in the symbol always being
800
+ # marked as available.
801
+ if '#include' in prefix:
802
+ head, main = self._have_prototype_templ()
803
+ else:
804
+ head, main = self._no_prototype_templ()
805
+ templ = head + stubs_fail + main + '\n'
806
+
807
+ res, cached = self.links(templ.format(**fargs), env, extra_args=extra_args,
808
+ dependencies=dependencies)
809
+ if res:
810
+ return True, cached
811
+
812
+ # MSVC does not have compiler __builtin_-s.
813
+ if self.get_id() in {'msvc', 'intel-cl'}:
814
+ return False, False
815
+
816
+ # Detect function as a built-in
817
+ #
818
+ # Some functions like alloca() are defined as compiler built-ins which
819
+ # are inlined by the compiler and you can't take their address, so we
820
+ # need to look for them differently. On nice compilers like clang, we
821
+ # can just directly use the __has_builtin() macro.
822
+ fargs['no_includes'] = '#include' not in prefix
823
+ is_builtin = funcname.startswith('__builtin_')
824
+ fargs['is_builtin'] = is_builtin
825
+ fargs['__builtin_'] = '' if is_builtin else '__builtin_'
826
+ t = '''{prefix}
827
+ int main(void) {{
828
+
829
+ /* With some toolchains (MSYS2/mingw for example) the compiler
830
+ * provides various builtins which are not really implemented and
831
+ * fall back to the stdlib where they aren't provided and fail at
832
+ * build/link time. In case the user provides a header, including
833
+ * the header didn't lead to the function being defined, and the
834
+ * function we are checking isn't a builtin itself we assume the
835
+ * builtin is not functional and we just error out. */
836
+ #if !{no_includes:d} && !defined({func}) && !{is_builtin:d}
837
+ #error "No definition for {__builtin_}{func} found in the prefix"
838
+ #endif
839
+
840
+ #ifdef __has_builtin
841
+ #if !__has_builtin({__builtin_}{func})
842
+ #error "{__builtin_}{func} not found"
843
+ #endif
844
+ #elif ! defined({func})
845
+ {__builtin_}{func};
846
+ #endif
847
+ return 0;
848
+ }}\n'''
849
+ return self.links(t.format(**fargs), env, extra_args=extra_args,
850
+ dependencies=dependencies)
851
+
852
+ def has_members(self, typename: str, membernames: T.List[str],
853
+ prefix: str, env: 'Environment', *,
854
+ extra_args: T.Union[None, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
855
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
856
+ if extra_args is None:
857
+ extra_args = []
858
+ # Create code that accesses all members
859
+ members = ''.join(f'foo.{member};\n' for member in membernames)
860
+ t = f'''{prefix}
861
+ void bar(void) {{
862
+ {typename} foo;
863
+ {members}
864
+ }}\n'''
865
+ return self.compiles(t, env, extra_args=extra_args,
866
+ dependencies=dependencies)
867
+
868
+ def has_type(self, typename: str, prefix: str, env: 'Environment',
869
+ extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]]], *,
870
+ dependencies: T.Optional[T.List['Dependency']] = None) -> T.Tuple[bool, bool]:
871
+ t = f'''{prefix}
872
+ void bar(void) {{
873
+ sizeof({typename});
874
+ }}\n'''
875
+ return self.compiles(t, env, extra_args=extra_args,
876
+ dependencies=dependencies)
877
+
878
+ def _symbols_have_underscore_prefix_searchbin(self, env: 'Environment') -> bool:
879
+ '''
880
+ Check if symbols have underscore prefix by compiling a small test binary
881
+ and then searching the binary for the string,
882
+ '''
883
+ symbol_name = b'meson_uscore_prefix'
884
+ code = '''#ifdef __cplusplus
885
+ extern "C" {
886
+ #endif
887
+ void ''' + symbol_name.decode() + ''' (void) {}
888
+ #ifdef __cplusplus
889
+ }
890
+ #endif
891
+ '''
892
+ args = self.get_compiler_check_args(CompileCheckMode.COMPILE)
893
+ n = '_symbols_have_underscore_prefix_searchbin'
894
+ with self._build_wrapper(code, env, extra_args=args, mode=CompileCheckMode.COMPILE, want_output=True) as p:
895
+ if p.returncode != 0:
896
+ raise RuntimeError(f'BUG: Unable to compile {n!r} check: {p.stderr}')
897
+ if not os.path.isfile(p.output_name):
898
+ raise RuntimeError(f'BUG: Can\'t find compiled test code for {n!r} check')
899
+ with open(p.output_name, 'rb') as o:
900
+ for line in o:
901
+ # Check if the underscore form of the symbol is somewhere
902
+ # in the output file.
903
+ if b'_' + symbol_name in line:
904
+ mlog.debug("Underscore prefix check found prefixed function in binary")
905
+ return True
906
+ # Else, check if the non-underscored form is present
907
+ elif symbol_name in line:
908
+ mlog.debug("Underscore prefix check found non-prefixed function in binary")
909
+ return False
910
+ raise RuntimeError(f'BUG: {n!r} check did not find symbol string in binary')
911
+
912
+ def _symbols_have_underscore_prefix_define(self, env: 'Environment') -> T.Optional[bool]:
913
+ '''
914
+ Check if symbols have underscore prefix by querying the
915
+ __USER_LABEL_PREFIX__ define that most compilers provide
916
+ for this. Return if functions have underscore prefix or None
917
+ if it was not possible to determine, like when the compiler
918
+ does not set the define or the define has an unexpected value.
919
+ '''
920
+ delim = '"MESON_HAVE_UNDERSCORE_DELIMITER" '
921
+ code = f'''
922
+ #ifndef __USER_LABEL_PREFIX__
923
+ #define MESON_UNDERSCORE_PREFIX unsupported
924
+ #else
925
+ #define MESON_UNDERSCORE_PREFIX __USER_LABEL_PREFIX__
926
+ #endif
927
+ {delim}MESON_UNDERSCORE_PREFIX
928
+ '''
929
+ with self._build_wrapper(code, env, mode=CompileCheckMode.PREPROCESS, want_output=False) as p:
930
+ if p.returncode != 0:
931
+ raise RuntimeError(f'BUG: Unable to preprocess _symbols_have_underscore_prefix_define check: {p.stdout}')
932
+ symbol_prefix = p.stdout.partition(delim)[-1].rstrip()
933
+
934
+ mlog.debug(f'Queried compiler for function prefix: __USER_LABEL_PREFIX__ is "{symbol_prefix!s}"')
935
+ if symbol_prefix == '_':
936
+ return True
937
+ elif symbol_prefix == '':
938
+ return False
939
+ else:
940
+ return None
941
+
942
+ def _symbols_have_underscore_prefix_list(self, env: 'Environment') -> T.Optional[bool]:
943
+ '''
944
+ Check if symbols have underscore prefix by consulting a hardcoded
945
+ list of cases where we know the results.
946
+ Return if functions have underscore prefix or None if unknown.
947
+ '''
948
+ m = env.machines[self.for_machine]
949
+ # Darwin always uses the underscore prefix, not matter what
950
+ if m.is_darwin():
951
+ return True
952
+ # Windows uses the underscore prefix on x86 (32bit) only
953
+ if m.is_windows() or m.is_cygwin():
954
+ return m.cpu_family == 'x86'
955
+ return None
956
+
957
+ def symbols_have_underscore_prefix(self, env: 'Environment') -> bool:
958
+ '''
959
+ Check if the compiler prefixes an underscore to global C symbols
960
+ '''
961
+ # First, try to query the compiler directly
962
+ result = self._symbols_have_underscore_prefix_define(env)
963
+ if result is not None:
964
+ return result
965
+
966
+ # Else, try to consult a hardcoded list of cases we know
967
+ # absolutely have an underscore prefix
968
+ result = self._symbols_have_underscore_prefix_list(env)
969
+ if result is not None:
970
+ return result
971
+
972
+ # As a last resort, try search in a compiled binary, which is the
973
+ # most unreliable way of checking this, see #5482
974
+ return self._symbols_have_underscore_prefix_searchbin(env)
975
+
976
+ def _get_patterns(self, env: 'Environment', prefixes: T.List[str], suffixes: T.List[str], shared: bool = False) -> T.List[str]:
977
+ patterns: T.List[str] = []
978
+ for p in prefixes:
979
+ for s in suffixes:
980
+ patterns.append(p + '{}.' + s)
981
+ if shared and env.machines[self.for_machine].is_openbsd():
982
+ # Shared libraries on OpenBSD can be named libfoo.so.X.Y:
983
+ # https://www.openbsd.org/faq/ports/specialtopics.html#SharedLibs
984
+ #
985
+ # This globbing is probably the best matching we can do since regex
986
+ # is expensive. It's wrong in many edge cases, but it will match
987
+ # correctly-named libraries and hopefully no one on OpenBSD names
988
+ # their files libfoo.so.9a.7b.1.0
989
+ for p in prefixes:
990
+ patterns.append(p + '{}.so.[0-9]*.[0-9]*')
991
+ return patterns
992
+
993
+ def get_library_naming(self, env: 'Environment', libtype: LibType, strict: bool = False) -> T.Tuple[str, ...]:
994
+ '''
995
+ Get library prefixes and suffixes for the target platform ordered by
996
+ priority
997
+ '''
998
+ stlibext = ['a']
999
+ # We've always allowed libname to be both `foo` and `libfoo`, and now
1000
+ # people depend on it. Also, some people use prebuilt `foo.so` instead
1001
+ # of `libfoo.so` for unknown reasons, and may also want to create
1002
+ # `foo.so` by setting name_prefix to ''
1003
+ if strict and not isinstance(self, VisualStudioLikeCompiler): # lib prefix is not usually used with msvc
1004
+ prefixes = ['lib']
1005
+ else:
1006
+ prefixes = ['lib', '']
1007
+ # Library suffixes and prefixes
1008
+ if env.machines[self.for_machine].is_darwin():
1009
+ shlibext = ['dylib', 'so']
1010
+ elif env.machines[self.for_machine].is_windows():
1011
+ # FIXME: .lib files can be import or static so we should read the
1012
+ # file, figure out which one it is, and reject the wrong kind.
1013
+ if isinstance(self, VisualStudioLikeCompiler):
1014
+ shlibext = ['lib']
1015
+ else:
1016
+ shlibext = ['dll.a', 'lib', 'dll']
1017
+ # Yep, static libraries can also be foo.lib
1018
+ stlibext += ['lib']
1019
+ elif env.machines[self.for_machine].is_cygwin():
1020
+ shlibext = ['dll', 'dll.a']
1021
+ prefixes = ['cyg'] + prefixes
1022
+ elif self.id.lower() == 'c6000' or self.id.lower() == 'ti':
1023
+ # TI C6000 compiler can use both extensions for static or dynamic libs.
1024
+ stlibext = ['a', 'lib']
1025
+ shlibext = ['dll', 'so']
1026
+ else:
1027
+ # Linux/BSDs
1028
+ shlibext = ['so']
1029
+ # Search priority
1030
+ if libtype is LibType.PREFER_SHARED:
1031
+ patterns = self._get_patterns(env, prefixes, shlibext, True)
1032
+ patterns.extend([x for x in self._get_patterns(env, prefixes, stlibext, False) if x not in patterns])
1033
+ elif libtype is LibType.PREFER_STATIC:
1034
+ patterns = self._get_patterns(env, prefixes, stlibext, False)
1035
+ patterns.extend([x for x in self._get_patterns(env, prefixes, shlibext, True) if x not in patterns])
1036
+ elif libtype is LibType.SHARED:
1037
+ patterns = self._get_patterns(env, prefixes, shlibext, True)
1038
+ else:
1039
+ assert libtype is LibType.STATIC
1040
+ patterns = self._get_patterns(env, prefixes, stlibext, False)
1041
+ return tuple(patterns)
1042
+
1043
+ @staticmethod
1044
+ def _sort_shlibs_openbsd(libs: T.List[str]) -> T.List[str]:
1045
+ def tuple_key(x: str) -> T.Tuple[int, ...]:
1046
+ ver = x.rsplit('.so.', maxsplit=1)[1]
1047
+ return tuple(int(i) for i in ver.split('.'))
1048
+
1049
+ filtered: T.List[str] = []
1050
+ for lib in libs:
1051
+ # Validate file as a shared library of type libfoo.so.X.Y
1052
+ ret = lib.rsplit('.so.', maxsplit=1)
1053
+ if len(ret) != 2:
1054
+ continue
1055
+ try:
1056
+ tuple(int(i) for i in ret[1].split('.'))
1057
+ except ValueError:
1058
+ continue
1059
+ filtered.append(lib)
1060
+ return sorted(filtered, key=tuple_key, reverse=True)
1061
+
1062
+ @classmethod
1063
+ def _get_trials_from_pattern(cls, pattern: str, directory: str, libname: str) -> T.List[Path]:
1064
+ f = Path(directory) / pattern.format(libname)
1065
+ # Globbing for OpenBSD
1066
+ if '*' in pattern:
1067
+ # NOTE: globbing matches directories and broken symlinks
1068
+ # so we have to do an isfile test on it later
1069
+ return [Path(x) for x in cls._sort_shlibs_openbsd(glob.glob(str(f)))]
1070
+ return [f]
1071
+
1072
+ @staticmethod
1073
+ def _get_file_from_list(env: Environment, paths: T.List[Path]) -> T.Optional[Path]:
1074
+ '''
1075
+ We just check whether the library exists. We can't do a link check
1076
+ because the library might have unresolved symbols that require other
1077
+ libraries. On macOS we check if the library matches our target
1078
+ architecture.
1079
+ '''
1080
+ for p in paths:
1081
+ if p.is_file():
1082
+
1083
+ if env.machines.host.is_darwin() and env.machines.build.is_darwin():
1084
+ # Run `lipo` and check if the library supports the arch we want
1085
+ archs = mesonlib.darwin_get_object_archs(str(p))
1086
+ if not archs or env.machines.host.cpu_family not in archs:
1087
+ mlog.debug(f'Rejected {p}, supports {archs} but need {env.machines.host.cpu_family}')
1088
+ continue
1089
+
1090
+ return p
1091
+
1092
+ return None
1093
+
1094
+ @functools.lru_cache()
1095
+ def output_is_64bit(self, env: 'Environment') -> bool:
1096
+ '''
1097
+ returns true if the output produced is 64-bit, false if 32-bit
1098
+ '''
1099
+ return self.sizeof('void *', '', env)[0] == 8
1100
+
1101
+ def _find_library_real(self, libname: str, env: 'Environment', extra_dirs: T.List[str], code: str, libtype: LibType, lib_prefix_warning: bool) -> T.Optional[T.List[str]]:
1102
+ # First try if we can just add the library as -l.
1103
+ # Gcc + co seem to prefer builtin lib dirs to -L dirs.
1104
+ # Only try to find std libs if no extra dirs specified.
1105
+ # The built-in search procedure will always favour .so and then always
1106
+ # search for .a. This is only allowed if libtype is LibType.PREFER_SHARED
1107
+ if ((not extra_dirs and libtype is LibType.PREFER_SHARED) or
1108
+ libname in self.internal_libs):
1109
+ cargs = ['-l' + libname]
1110
+ largs = self.get_linker_always_args() + self.get_allow_undefined_link_args()
1111
+ extra_args = cargs + self.linker_to_compiler_args(largs)
1112
+
1113
+ if self.links(code, env, extra_args=extra_args, disable_cache=True)[0]:
1114
+ return cargs
1115
+ # Don't do a manual search for internal libs
1116
+ if libname in self.internal_libs:
1117
+ return None
1118
+ # Not found or we want to use a specific libtype? Try to find the
1119
+ # library file itself.
1120
+ patterns = self.get_library_naming(env, libtype)
1121
+ # try to detect if we are 64-bit or 32-bit. If we can't
1122
+ # detect, we will just skip path validity checks done in
1123
+ # get_library_dirs() call
1124
+ try:
1125
+ if self.output_is_64bit(env):
1126
+ elf_class = 2
1127
+ else:
1128
+ elf_class = 1
1129
+ except (mesonlib.MesonException, KeyError): # TODO evaluate if catching KeyError is wanted here
1130
+ elf_class = 0
1131
+ # Search in the specified dirs, and then in the system libraries
1132
+ for d in itertools.chain(extra_dirs, self.get_library_dirs(env, elf_class)):
1133
+ for p in patterns:
1134
+ trials = self._get_trials_from_pattern(p, d, libname)
1135
+ if not trials:
1136
+ continue
1137
+ trial = self._get_file_from_list(env, trials)
1138
+ if not trial:
1139
+ continue
1140
+ if libname.startswith('lib') and trial.name.startswith(libname) and lib_prefix_warning:
1141
+ mlog.warning(f'find_library({libname!r}) starting in "lib" only works by accident and is not portable')
1142
+ return [trial.as_posix()]
1143
+ return None
1144
+
1145
+ def _find_library_impl(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
1146
+ code: str, libtype: LibType, lib_prefix_warning: bool) -> T.Optional[T.List[str]]:
1147
+ # These libraries are either built-in or invalid
1148
+ if libname in self.ignore_libs:
1149
+ return []
1150
+ if isinstance(extra_dirs, str):
1151
+ extra_dirs = [extra_dirs]
1152
+ key = (tuple(self.exelist), libname, tuple(extra_dirs), code, libtype)
1153
+ if key not in self.find_library_cache:
1154
+ value = self._find_library_real(libname, env, extra_dirs, code, libtype, lib_prefix_warning)
1155
+ self.find_library_cache[key] = value
1156
+ else:
1157
+ value = self.find_library_cache[key]
1158
+ if value is None:
1159
+ return None
1160
+ return value.copy()
1161
+
1162
+ def find_library(self, libname: str, env: 'Environment', extra_dirs: T.List[str],
1163
+ libtype: LibType = LibType.PREFER_SHARED, lib_prefix_warning: bool = True) -> T.Optional[T.List[str]]:
1164
+ code = 'int main(void) { return 0; }\n'
1165
+ return self._find_library_impl(libname, env, extra_dirs, code, libtype, lib_prefix_warning)
1166
+
1167
+ def find_framework_paths(self, env: 'Environment') -> T.List[str]:
1168
+ '''
1169
+ These are usually /Library/Frameworks and /System/Library/Frameworks,
1170
+ unless you select a particular macOS SDK with the -isysroot flag.
1171
+ You can also add to this by setting -F in CFLAGS.
1172
+ '''
1173
+ # TODO: this really needs to be *AppleClang*, not just any clang.
1174
+ if self.id != 'clang':
1175
+ raise mesonlib.MesonException('Cannot find framework path with non-clang compiler')
1176
+ # Construct the compiler command-line
1177
+ commands = self.get_exelist(ccache=False) + ['-v', '-E', '-']
1178
+ commands += self.get_always_args()
1179
+ # Add CFLAGS/CXXFLAGS/OBJCFLAGS/OBJCXXFLAGS from the env
1180
+ commands += env.coredata.get_external_args(self.for_machine, self.language)
1181
+ mlog.debug('Finding framework path by running: ', ' '.join(commands), '\n')
1182
+ os_env = os.environ.copy()
1183
+ os_env['LC_ALL'] = 'C'
1184
+ _, _, stde = mesonlib.Popen_safe(commands, env=os_env, stdin=subprocess.PIPE)
1185
+ paths: T.List[str] = []
1186
+ for line in stde.split('\n'):
1187
+ if '(framework directory)' not in line:
1188
+ continue
1189
+ # line is of the form:
1190
+ # ` /path/to/framework (framework directory)`
1191
+ paths.append(line[:-21].strip())
1192
+ return paths
1193
+
1194
+ def _find_framework_real(self, name: str, env: 'Environment', extra_dirs: T.List[str], allow_system: bool) -> T.Optional[T.List[str]]:
1195
+ code = 'int main(void) { return 0; }'
1196
+ link_args: T.List[str] = []
1197
+ for d in extra_dirs:
1198
+ link_args += ['-F' + d]
1199
+ # We can pass -Z to disable searching in the system frameworks, but
1200
+ # then we must also pass -L/usr/lib to pick up libSystem.dylib
1201
+ extra_args = [] if allow_system else ['-Z', '-L/usr/lib']
1202
+ link_args += ['-framework', name]
1203
+ if self.links(code, env, extra_args=(extra_args + link_args), disable_cache=True)[0]:
1204
+ return link_args
1205
+ return None
1206
+
1207
+ def _find_framework_impl(self, name: str, env: 'Environment', extra_dirs: T.List[str],
1208
+ allow_system: bool) -> T.Optional[T.List[str]]:
1209
+ if isinstance(extra_dirs, str):
1210
+ extra_dirs = [extra_dirs]
1211
+ key = (tuple(self.exelist), name, tuple(extra_dirs), allow_system)
1212
+ if key in self.find_framework_cache:
1213
+ value = self.find_framework_cache[key]
1214
+ else:
1215
+ value = self._find_framework_real(name, env, extra_dirs, allow_system)
1216
+ self.find_framework_cache[key] = value
1217
+ if value is None:
1218
+ return None
1219
+ return value.copy()
1220
+
1221
+ def find_framework(self, name: str, env: 'Environment', extra_dirs: T.List[str],
1222
+ allow_system: bool = True) -> T.Optional[T.List[str]]:
1223
+ '''
1224
+ Finds the framework with the specified name, and returns link args for
1225
+ the same or returns None when the framework is not found.
1226
+ '''
1227
+ # TODO: should probably check for macOS?
1228
+ return self._find_framework_impl(name, env, extra_dirs, allow_system)
1229
+
1230
+ def get_crt_compile_args(self, crt_val: str, buildtype: str) -> T.List[str]:
1231
+ # TODO: does this belong here or in GnuLike or maybe PosixLike?
1232
+ return []
1233
+
1234
+ def get_crt_link_args(self, crt_val: str, buildtype: str) -> T.List[str]:
1235
+ # TODO: does this belong here or in GnuLike or maybe PosixLike?
1236
+ return []
1237
+
1238
+ def thread_flags(self, env: 'Environment') -> T.List[str]:
1239
+ # TODO: does this belong here or in GnuLike or maybe PosixLike?
1240
+ host_m = env.machines[self.for_machine]
1241
+ if host_m.is_haiku() or host_m.is_darwin():
1242
+ return []
1243
+ return ['-pthread']
1244
+
1245
+ def linker_to_compiler_args(self, args: T.List[str]) -> T.List[str]:
1246
+ return args.copy()
1247
+
1248
+ def has_arguments(self, args: T.List[str], env: 'Environment', code: str,
1249
+ mode: CompileCheckMode) -> T.Tuple[bool, bool]:
1250
+ return self.compiles(code, env, extra_args=args, mode=mode)
1251
+
1252
+ def _has_multi_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]:
1253
+ new_args: T.List[str] = []
1254
+ for arg in args:
1255
+ # some compilers, e.g. GCC, don't warn for unsupported warning-disable
1256
+ # flags, so when we are testing a flag like "-Wno-forgotten-towel", also
1257
+ # check the equivalent enable flag too "-Wforgotten-towel"
1258
+ if arg.startswith('-Wno-'):
1259
+ new_args.append('-W' + arg[5:])
1260
+ if arg.startswith('-Wl,'):
1261
+ mlog.warning(f'{arg} looks like a linker argument, '
1262
+ 'but has_argument and other similar methods only '
1263
+ 'support checking compiler arguments. Using them '
1264
+ 'to check linker arguments are never supported, '
1265
+ 'and results are likely to be wrong regardless of '
1266
+ 'the compiler you are using. has_link_argument or '
1267
+ 'other similar method can be used instead.')
1268
+ new_args.append(arg)
1269
+ return self.has_arguments(new_args, env, code, mode=CompileCheckMode.COMPILE)
1270
+
1271
+ def has_multi_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
1272
+ return self._has_multi_arguments(args, env, 'extern int i;\nint i;\n')
1273
+
1274
+ def _has_multi_link_arguments(self, args: T.List[str], env: 'Environment', code: str) -> T.Tuple[bool, bool]:
1275
+ # First time we check for link flags we need to first check if we have
1276
+ # --fatal-warnings, otherwise some linker checks could give some
1277
+ # false positive.
1278
+ args = self.linker.fatal_warnings() + args
1279
+ args = self.linker_to_compiler_args(args)
1280
+ return self.has_arguments(args, env, code, mode=CompileCheckMode.LINK)
1281
+
1282
+ def has_multi_link_arguments(self, args: T.List[str], env: 'Environment') -> T.Tuple[bool, bool]:
1283
+ return self._has_multi_link_arguments(args, env, 'int main(void) { return 0; }\n')
1284
+
1285
+ @staticmethod
1286
+ def _concatenate_string_literals(s: str) -> str:
1287
+ pattern = re.compile(r'(?P<pre>.*([^\\]")|^")(?P<str1>([^\\"]|\\.)*)"\s+"(?P<str2>([^\\"]|\\.)*)(?P<post>".*)')
1288
+ ret = s
1289
+ m = pattern.match(ret)
1290
+ while m:
1291
+ ret = ''.join(m.group('pre', 'str1', 'str2', 'post'))
1292
+ m = pattern.match(ret)
1293
+ return ret
1294
+
1295
+ def get_has_func_attribute_extra_args(self, name: str) -> T.List[str]:
1296
+ # Most compilers (such as GCC and Clang) only warn about unknown or
1297
+ # ignored attributes, so force an error. Overridden in GCC and Clang
1298
+ # mixins.
1299
+ return ['-Werror']
1300
+
1301
+ def has_func_attribute(self, name: str, env: 'Environment') -> T.Tuple[bool, bool]:
1302
+ # Just assume that if we're not on windows that dllimport and dllexport
1303
+ # don't work
1304
+ m = env.machines[self.for_machine]
1305
+ if not (m.is_windows() or m.is_cygwin()):
1306
+ if name in {'dllimport', 'dllexport'}:
1307
+ return False, False
1308
+
1309
+ return self.compiles(self.attribute_check_func(name), env,
1310
+ extra_args=self.get_has_func_attribute_extra_args(name))
1311
+
1312
+ def get_assert_args(self, disable: bool) -> T.List[str]:
1313
+ if disable:
1314
+ return ['-DNDEBUG']
1315
+ return []
1316
+
1317
+ @functools.lru_cache(maxsize=None)
1318
+ def can_compile(self, src: 'mesonlib.FileOrString') -> bool:
1319
+ # Files we preprocess can be anything, e.g. .in
1320
+ if self.mode == 'PREPROCESSOR':
1321
+ return True
1322
+ return super().can_compile(src)
1323
+
1324
+ def get_preprocessor(self) -> Compiler:
1325
+ if not self.preprocessor:
1326
+ self.preprocessor = copy.copy(self)
1327
+ self.preprocessor.exelist = self.exelist + self.get_preprocess_to_file_args()
1328
+ self.preprocessor.mode = 'PREPROCESSOR'
1329
+ self.modes.append(self.preprocessor)
1330
+ return self.preprocessor