frida 16.2.1 → 16.2.3

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,1781 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright 2014-2021 The Meson development team
3
+
4
+ from __future__ import annotations
5
+
6
+ import functools, uuid, os, operator
7
+ import typing as T
8
+
9
+ from . import backends
10
+ from .. import build
11
+ from .. import mesonlib
12
+ from .. import mlog
13
+ from ..mesonlib import MesonBugException, MesonException, OptionKey
14
+
15
+ if T.TYPE_CHECKING:
16
+ from ..interpreter import Interpreter
17
+
18
+ INDENT = '\t'
19
+ XCODETYPEMAP = {'c': 'sourcecode.c.c',
20
+ 'a': 'archive.ar',
21
+ 'cc': 'sourcecode.cpp.cpp',
22
+ 'cxx': 'sourcecode.cpp.cpp',
23
+ 'cpp': 'sourcecode.cpp.cpp',
24
+ 'c++': 'sourcecode.cpp.cpp',
25
+ 'm': 'sourcecode.c.objc',
26
+ 'mm': 'sourcecode.cpp.objcpp',
27
+ 'h': 'sourcecode.c.h',
28
+ 'hpp': 'sourcecode.cpp.h',
29
+ 'hxx': 'sourcecode.cpp.h',
30
+ 'hh': 'sourcecode.cpp.hh',
31
+ 'inc': 'sourcecode.c.h',
32
+ 'swift': 'sourcecode.swift',
33
+ 'dylib': 'compiled.mach-o.dylib',
34
+ 'o': 'compiled.mach-o.objfile',
35
+ 's': 'sourcecode.asm',
36
+ 'asm': 'sourcecode.asm',
37
+ 'metal': 'sourcecode.metal',
38
+ 'glsl': 'sourcecode.glsl',
39
+ }
40
+ LANGNAMEMAP = {'c': 'C',
41
+ 'cpp': 'CPLUSPLUS',
42
+ 'objc': 'OBJC',
43
+ 'objcpp': 'OBJCPLUSPLUS',
44
+ 'swift': 'SWIFT_'
45
+ }
46
+ OPT2XCODEOPT = {'plain': None,
47
+ '0': '0',
48
+ 'g': '0',
49
+ '1': '1',
50
+ '2': '2',
51
+ '3': '3',
52
+ 's': 's',
53
+ }
54
+ BOOL2XCODEBOOL = {True: 'YES', False: 'NO'}
55
+ LINKABLE_EXTENSIONS = {'.o', '.a', '.obj', '.so', '.dylib'}
56
+
57
+ class FileTreeEntry:
58
+
59
+ def __init__(self) -> None:
60
+ self.subdirs: T.Dict[str, FileTreeEntry] = {}
61
+ self.targets: T.List[build.BuildTarget] = []
62
+
63
+ class PbxArray:
64
+ def __init__(self) -> None:
65
+ self.items: T.List[PbxArrayItem] = []
66
+
67
+ def add_item(self, item: T.Union[PbxArrayItem, str], comment: str = '') -> None:
68
+ if isinstance(item, PbxArrayItem):
69
+ self.items.append(item)
70
+ else:
71
+ self.items.append(PbxArrayItem(item, comment))
72
+
73
+ def write(self, ofile: T.TextIO, indent_level: int) -> None:
74
+ ofile.write('(\n')
75
+ indent_level += 1
76
+ for i in self.items:
77
+ if i.comment:
78
+ ofile.write(indent_level*INDENT + f'{i.value} {i.comment},\n')
79
+ else:
80
+ ofile.write(indent_level*INDENT + f'{i.value},\n')
81
+ indent_level -= 1
82
+ ofile.write(indent_level*INDENT + ');\n')
83
+
84
+ class PbxArrayItem:
85
+ def __init__(self, value: str, comment: str = ''):
86
+ self.value = value
87
+ if comment:
88
+ if '/*' in comment:
89
+ self.comment = comment
90
+ else:
91
+ self.comment = f'/* {comment} */'
92
+ else:
93
+ self.comment = comment
94
+
95
+ class PbxComment:
96
+ def __init__(self, text: str):
97
+ assert isinstance(text, str)
98
+ assert '/*' not in text
99
+ self.text = f'/* {text} */'
100
+
101
+ def write(self, ofile: T.TextIO, indent_level: int) -> None:
102
+ ofile.write(f'\n{self.text}\n')
103
+
104
+ class PbxDictItem:
105
+ def __init__(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = ''):
106
+ self.key = key
107
+ self.value = value
108
+ if comment:
109
+ if '/*' in comment:
110
+ self.comment = comment
111
+ else:
112
+ self.comment = f'/* {comment} */'
113
+ else:
114
+ self.comment = comment
115
+
116
+ class PbxDict:
117
+ def __init__(self) -> None:
118
+ # This class is a bit weird, because we want to write PBX dicts in
119
+ # defined order _and_ we want to write intermediate comments also in order.
120
+ self.keys: T.Set[str] = set()
121
+ self.items: T.List[T.Union[PbxDictItem, PbxComment]] = []
122
+
123
+ def add_item(self, key: str, value: T.Union[PbxArray, PbxDict, str, int], comment: str = '') -> None:
124
+ assert key not in self.keys
125
+ item = PbxDictItem(key, value, comment)
126
+ self.keys.add(key)
127
+ self.items.append(item)
128
+
129
+ def has_item(self, key: str) -> bool:
130
+ return key in self.keys
131
+
132
+ def add_comment(self, comment: PbxComment) -> None:
133
+ assert isinstance(comment, PbxComment)
134
+ self.items.append(comment)
135
+
136
+ def write(self, ofile: T.TextIO, indent_level: int) -> None:
137
+ ofile.write('{\n')
138
+ indent_level += 1
139
+ for i in self.items:
140
+ if isinstance(i, PbxComment):
141
+ i.write(ofile, indent_level)
142
+ elif isinstance(i, PbxDictItem):
143
+ if isinstance(i.value, (str, int)):
144
+ if i.comment:
145
+ ofile.write(indent_level*INDENT + f'{i.key} = {i.value} {i.comment};\n')
146
+ else:
147
+ ofile.write(indent_level*INDENT + f'{i.key} = {i.value};\n')
148
+ elif isinstance(i.value, PbxDict):
149
+ if i.comment:
150
+ ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ')
151
+ else:
152
+ ofile.write(indent_level*INDENT + f'{i.key} = ')
153
+ i.value.write(ofile, indent_level)
154
+ elif isinstance(i.value, PbxArray):
155
+ if i.comment:
156
+ ofile.write(indent_level*INDENT + f'{i.key} {i.comment} = ')
157
+ else:
158
+ ofile.write(indent_level*INDENT + f'{i.key} = ')
159
+ i.value.write(ofile, indent_level)
160
+ else:
161
+ print(i)
162
+ print(i.key)
163
+ print(i.value)
164
+ raise RuntimeError('missing code')
165
+ else:
166
+ print(i)
167
+ raise RuntimeError('missing code2')
168
+
169
+ indent_level -= 1
170
+ ofile.write(indent_level*INDENT + '}')
171
+ if indent_level == 0:
172
+ ofile.write('\n')
173
+ else:
174
+ ofile.write(';\n')
175
+
176
+ class XCodeBackend(backends.Backend):
177
+
178
+ name = 'xcode'
179
+
180
+ def __init__(self, build: T.Optional[build.Build], interpreter: T.Optional[Interpreter]):
181
+ super().__init__(build, interpreter)
182
+ self.project_uid = self.environment.coredata.lang_guids['default'].replace('-', '')[:24]
183
+ self.buildtype = T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype')))
184
+ self.project_conflist = self.gen_id()
185
+ self.maingroup_id = self.gen_id()
186
+ self.all_id = self.gen_id()
187
+ self.all_buildconf_id = self.gen_id()
188
+ self.buildtypes = [self.buildtype]
189
+ self.test_id = self.gen_id()
190
+ self.test_command_id = self.gen_id()
191
+ self.test_buildconf_id = self.gen_id()
192
+ self.regen_id = self.gen_id()
193
+ self.regen_command_id = self.gen_id()
194
+ self.regen_buildconf_id = self.gen_id()
195
+ self.regen_dependency_id = self.gen_id()
196
+ self.top_level_dict = PbxDict()
197
+ self.generator_outputs = {}
198
+ self.arch = self.build.environment.machines.host.cpu
199
+ if self.arch == 'aarch64':
200
+ self.arch = 'arm64'
201
+ # In Xcode files are not accessed via their file names, but rather every one of them
202
+ # gets an unique id. More precisely they get one unique id per target they are used
203
+ # in. If you generate only one id per file and use them, compilation will work but the
204
+ # UI will only show the file in one target but not the others. Thus they key is
205
+ # a tuple containing the target and filename.
206
+ self.buildfile_ids = {}
207
+ # That is not enough, though. Each target/file combination also gets a unique id
208
+ # in the file reference section. Because why not. This means that a source file
209
+ # that is used in two targets gets a total of four unique ID numbers.
210
+ self.fileref_ids = {}
211
+
212
+ def write_pbxfile(self, top_level_dict, ofilename) -> None:
213
+ tmpname = ofilename + '.tmp'
214
+ with open(tmpname, 'w', encoding='utf-8') as ofile:
215
+ ofile.write('// !$*UTF8*$!\n')
216
+ top_level_dict.write(ofile, 0)
217
+ os.replace(tmpname, ofilename)
218
+
219
+ def gen_id(self) -> str:
220
+ return str(uuid.uuid4()).upper().replace('-', '')[:24]
221
+
222
+ @functools.lru_cache(maxsize=None)
223
+ def get_target_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str:
224
+ dirname = os.path.join(target.get_source_subdir(), T.cast('str', self.environment.coredata.get_option(OptionKey('buildtype'))))
225
+ #os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True)
226
+ return dirname
227
+
228
+ def get_custom_target_output_dir(self, target: T.Union[build.Target, build.CustomTargetIndex]) -> str:
229
+ dirname = target.get_output_subdir()
230
+ os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True)
231
+ return dirname
232
+
233
+ def object_filename_from_source(self, target: build.BuildTarget, source: mesonlib.FileOrString, targetdir: T.Optional[str] = None) -> str:
234
+ # Xcode has the following naming scheme:
235
+ # projectname.build/debug/prog@exe.build/Objects-normal/x86_64/func.o
236
+ project = self.build.project_name
237
+ buildtype = self.buildtype
238
+ tname = target.get_id()
239
+ if isinstance(source, mesonlib.File):
240
+ source = source.fname
241
+ stem = os.path.splitext(os.path.basename(source))[0]
242
+ # Append "build" before the actual object path to match OBJROOT
243
+ obj_path = f'build/{project}.build/{buildtype}/{tname}.build/Objects-normal/{self.arch}/{stem}.o'
244
+ return obj_path
245
+
246
+ def determine_swift_dep_dirs(self, target: build.BuildTarget) -> T.List[str]:
247
+ result: T.List[str] = []
248
+ for l in target.link_targets:
249
+ # Xcode does not recognize our private directories, so we have to use its build directories instead.
250
+ result.append(os.path.join(self.environment.get_build_dir(), self.get_target_dir(l)))
251
+ return result
252
+
253
+ def generate(self, capture: bool = False, vslite_ctx: dict = None) -> None:
254
+ # Check for (currently) unexpected capture arg use cases -
255
+ if capture:
256
+ raise MesonBugException('We do not expect the xcode backend to generate with \'capture = True\'')
257
+ if vslite_ctx:
258
+ raise MesonBugException('We do not expect the xcode backend to be given a valid \'vslite_ctx\'')
259
+ self.serialize_tests()
260
+ # Cache the result as the method rebuilds the array every time it is called.
261
+ self.build_targets = self.build.get_build_targets()
262
+ self.custom_targets = self.build.get_custom_targets()
263
+ self.generate_filemap()
264
+ self.generate_buildstylemap()
265
+ self.generate_build_phase_map()
266
+ self.generate_build_configuration_map()
267
+ self.generate_build_configurationlist_map()
268
+ self.generate_project_configurations_map()
269
+ self.generate_buildall_configurations_map()
270
+ self.generate_test_configurations_map()
271
+ self.generate_native_target_map()
272
+ self.generate_native_frameworks_map()
273
+ self.generate_custom_target_map()
274
+ self.generate_generator_target_map()
275
+ self.generate_source_phase_map()
276
+ self.generate_target_dependency_map()
277
+ self.generate_pbxdep_map()
278
+ self.generate_containerproxy_map()
279
+ self.generate_target_file_maps()
280
+ self.generate_build_file_maps()
281
+ self.proj_dir = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.xcodeproj')
282
+ os.makedirs(self.proj_dir, exist_ok=True)
283
+ self.proj_file = os.path.join(self.proj_dir, 'project.pbxproj')
284
+ objects_dict = self.generate_prefix(self.top_level_dict)
285
+ objects_dict.add_comment(PbxComment('Begin PBXAggregateTarget section'))
286
+ self.generate_pbx_aggregate_target(objects_dict)
287
+ objects_dict.add_comment(PbxComment('End PBXAggregateTarget section'))
288
+ objects_dict.add_comment(PbxComment('Begin PBXBuildFile section'))
289
+ self.generate_pbx_build_file(objects_dict)
290
+ objects_dict.add_comment(PbxComment('End PBXBuildFile section'))
291
+ objects_dict.add_comment(PbxComment('Begin PBXBuildStyle section'))
292
+ self.generate_pbx_build_style(objects_dict)
293
+ objects_dict.add_comment(PbxComment('End PBXBuildStyle section'))
294
+ objects_dict.add_comment(PbxComment('Begin PBXContainerItemProxy section'))
295
+ self.generate_pbx_container_item_proxy(objects_dict)
296
+ objects_dict.add_comment(PbxComment('End PBXContainerItemProxy section'))
297
+ objects_dict.add_comment(PbxComment('Begin PBXFileReference section'))
298
+ self.generate_pbx_file_reference(objects_dict)
299
+ objects_dict.add_comment(PbxComment('End PBXFileReference section'))
300
+ objects_dict.add_comment(PbxComment('Begin PBXFrameworksBuildPhase section'))
301
+ self.generate_pbx_frameworks_buildphase(objects_dict)
302
+ objects_dict.add_comment(PbxComment('End PBXFrameworksBuildPhase section'))
303
+ objects_dict.add_comment(PbxComment('Begin PBXGroup section'))
304
+ self.generate_pbx_group(objects_dict)
305
+ objects_dict.add_comment(PbxComment('End PBXGroup section'))
306
+ objects_dict.add_comment(PbxComment('Begin PBXNativeTarget section'))
307
+ self.generate_pbx_native_target(objects_dict)
308
+ objects_dict.add_comment(PbxComment('End PBXNativeTarget section'))
309
+ objects_dict.add_comment(PbxComment('Begin PBXProject section'))
310
+ self.generate_pbx_project(objects_dict)
311
+ objects_dict.add_comment(PbxComment('End PBXProject section'))
312
+ objects_dict.add_comment(PbxComment('Begin PBXShellScriptBuildPhase section'))
313
+ self.generate_pbx_shell_build_phase(objects_dict)
314
+ objects_dict.add_comment(PbxComment('End PBXShellScriptBuildPhase section'))
315
+ objects_dict.add_comment(PbxComment('Begin PBXSourcesBuildPhase section'))
316
+ self.generate_pbx_sources_build_phase(objects_dict)
317
+ objects_dict.add_comment(PbxComment('End PBXSourcesBuildPhase section'))
318
+ objects_dict.add_comment(PbxComment('Begin PBXTargetDependency section'))
319
+ self.generate_pbx_target_dependency(objects_dict)
320
+ objects_dict.add_comment(PbxComment('End PBXTargetDependency section'))
321
+ objects_dict.add_comment(PbxComment('Begin XCBuildConfiguration section'))
322
+ self.generate_xc_build_configuration(objects_dict)
323
+ objects_dict.add_comment(PbxComment('End XCBuildConfiguration section'))
324
+ objects_dict.add_comment(PbxComment('Begin XCConfigurationList section'))
325
+ self.generate_xc_configurationList(objects_dict)
326
+ objects_dict.add_comment(PbxComment('End XCConfigurationList section'))
327
+ self.generate_suffix(self.top_level_dict)
328
+ self.write_pbxfile(self.top_level_dict, self.proj_file)
329
+ self.generate_regen_info()
330
+
331
+ def get_xcodetype(self, fname: str) -> str:
332
+ extension = fname.split('.')[-1]
333
+ if extension == 'C':
334
+ extension = 'cpp'
335
+ xcodetype = XCODETYPEMAP.get(extension.lower())
336
+ if not xcodetype:
337
+ xcodetype = 'sourcecode.unknown'
338
+ return xcodetype
339
+
340
+ def generate_filemap(self) -> None:
341
+ self.filemap = {} # Key is source file relative to src root.
342
+ self.target_filemap = {}
343
+ for name, t in self.build_targets.items():
344
+ for s in t.sources:
345
+ if isinstance(s, mesonlib.File):
346
+ s = os.path.join(s.subdir, s.fname)
347
+ self.filemap[s] = self.gen_id()
348
+ for o in t.objects:
349
+ if isinstance(o, str):
350
+ o = os.path.join(t.subdir, o)
351
+ self.filemap[o] = self.gen_id()
352
+ for e in t.extra_files:
353
+ if isinstance(e, mesonlib.File):
354
+ e = os.path.join(e.subdir, e.fname)
355
+ self.filemap[e] = self.gen_id()
356
+ else:
357
+ e = os.path.join(t.subdir, e)
358
+ self.filemap[e] = self.gen_id()
359
+ self.target_filemap[name] = self.gen_id()
360
+
361
+ def generate_buildstylemap(self) -> None:
362
+ self.buildstylemap = {self.buildtype: self.gen_id()}
363
+
364
+ def generate_build_phase_map(self) -> None:
365
+ for tname, t in self.build_targets.items():
366
+ # generate id for our own target-name
367
+ t.buildphasemap = {}
368
+ t.buildphasemap[tname] = self.gen_id()
369
+ # each target can have it's own Frameworks/Sources/..., generate id's for those
370
+ t.buildphasemap['Frameworks'] = self.gen_id()
371
+ t.buildphasemap['Resources'] = self.gen_id()
372
+ t.buildphasemap['Sources'] = self.gen_id()
373
+
374
+ def generate_build_configuration_map(self) -> None:
375
+ self.buildconfmap = {}
376
+ for t in self.build_targets:
377
+ bconfs = {self.buildtype: self.gen_id()}
378
+ self.buildconfmap[t] = bconfs
379
+ for t in self.custom_targets:
380
+ bconfs = {self.buildtype: self.gen_id()}
381
+ self.buildconfmap[t] = bconfs
382
+
383
+ def generate_project_configurations_map(self) -> None:
384
+ self.project_configurations = {self.buildtype: self.gen_id()}
385
+
386
+ def generate_buildall_configurations_map(self) -> None:
387
+ self.buildall_configurations = {self.buildtype: self.gen_id()}
388
+
389
+ def generate_test_configurations_map(self) -> None:
390
+ self.test_configurations = {self.buildtype: self.gen_id()}
391
+
392
+ def generate_build_configurationlist_map(self) -> None:
393
+ self.buildconflistmap = {}
394
+ for t in self.build_targets:
395
+ self.buildconflistmap[t] = self.gen_id()
396
+ for t in self.custom_targets:
397
+ self.buildconflistmap[t] = self.gen_id()
398
+
399
+ def generate_native_target_map(self) -> None:
400
+ self.native_targets = {}
401
+ for t in self.build_targets:
402
+ self.native_targets[t] = self.gen_id()
403
+
404
+ def generate_custom_target_map(self) -> None:
405
+ self.shell_targets = {}
406
+ self.custom_target_output_buildfile = {}
407
+ self.custom_target_output_fileref = {}
408
+ for tname, t in self.custom_targets.items():
409
+ self.shell_targets[tname] = self.gen_id()
410
+ if not isinstance(t, build.CustomTarget):
411
+ continue
412
+ (srcs, ofilenames, cmd) = self.eval_custom_target_command(t)
413
+ for o in ofilenames:
414
+ self.custom_target_output_buildfile[o] = self.gen_id()
415
+ self.custom_target_output_fileref[o] = self.gen_id()
416
+
417
+ def generate_generator_target_map(self) -> None:
418
+ # Generator objects do not have natural unique ids
419
+ # so use a counter.
420
+ self.generator_fileref_ids = {}
421
+ self.generator_buildfile_ids = {}
422
+ for tname, t in self.build_targets.items():
423
+ generator_id = 0
424
+ for genlist in t.generated:
425
+ if not isinstance(genlist, build.GeneratedList):
426
+ continue
427
+ self.gen_single_target_map(genlist, tname, t, generator_id)
428
+ generator_id += 1
429
+ # FIXME add outputs.
430
+ for tname, t in self.custom_targets.items():
431
+ generator_id = 0
432
+ for genlist in t.sources:
433
+ if not isinstance(genlist, build.GeneratedList):
434
+ continue
435
+ self.gen_single_target_map(genlist, tname, t, generator_id)
436
+ generator_id += 1
437
+
438
+ def gen_single_target_map(self, genlist, tname, t, generator_id) -> None:
439
+ k = (tname, generator_id)
440
+ assert k not in self.shell_targets
441
+ self.shell_targets[k] = self.gen_id()
442
+ ofile_abs = []
443
+ for i in genlist.get_inputs():
444
+ for o_base in genlist.get_outputs_for(i):
445
+ o = os.path.join(self.get_target_private_dir(t), o_base)
446
+ ofile_abs.append(os.path.join(self.environment.get_build_dir(), o))
447
+ assert k not in self.generator_outputs
448
+ self.generator_outputs[k] = ofile_abs
449
+ buildfile_ids = []
450
+ fileref_ids = []
451
+ for i in range(len(ofile_abs)):
452
+ buildfile_ids.append(self.gen_id())
453
+ fileref_ids.append(self.gen_id())
454
+ self.generator_buildfile_ids[k] = buildfile_ids
455
+ self.generator_fileref_ids[k] = fileref_ids
456
+
457
+ def generate_native_frameworks_map(self) -> None:
458
+ self.native_frameworks = {}
459
+ self.native_frameworks_fileref = {}
460
+ for t in self.build_targets.values():
461
+ for dep in t.get_external_deps():
462
+ if dep.name == 'appleframeworks':
463
+ for f in dep.frameworks:
464
+ self.native_frameworks[f] = self.gen_id()
465
+ self.native_frameworks_fileref[f] = self.gen_id()
466
+
467
+ def generate_target_dependency_map(self) -> None:
468
+ self.target_dependency_map = {}
469
+ for tname, t in self.build_targets.items():
470
+ for target in t.link_targets:
471
+ if isinstance(target, build.CustomTargetIndex):
472
+ k = (tname, target.target.get_basename())
473
+ if k in self.target_dependency_map:
474
+ continue
475
+ else:
476
+ k = (tname, target.get_basename())
477
+ assert k not in self.target_dependency_map
478
+ self.target_dependency_map[k] = self.gen_id()
479
+ for tname, t in self.custom_targets.items():
480
+ k = tname
481
+ assert k not in self.target_dependency_map
482
+ self.target_dependency_map[k] = self.gen_id()
483
+
484
+ def generate_pbxdep_map(self) -> None:
485
+ self.pbx_dep_map = {}
486
+ self.pbx_custom_dep_map = {}
487
+ for t in self.build_targets:
488
+ self.pbx_dep_map[t] = self.gen_id()
489
+ for t in self.custom_targets:
490
+ self.pbx_custom_dep_map[t] = self.gen_id()
491
+
492
+ def generate_containerproxy_map(self) -> None:
493
+ self.containerproxy_map = {}
494
+ for t in self.build_targets:
495
+ self.containerproxy_map[t] = self.gen_id()
496
+
497
+ def generate_target_file_maps(self) -> None:
498
+ self.generate_target_file_maps_impl(self.build_targets)
499
+ self.generate_target_file_maps_impl(self.custom_targets)
500
+
501
+ def generate_target_file_maps_impl(self, targets) -> None:
502
+ for tname, t in targets.items():
503
+ for s in t.sources:
504
+ if isinstance(s, mesonlib.File):
505
+ s = os.path.join(s.subdir, s.fname)
506
+ if not isinstance(s, str):
507
+ continue
508
+ k = (tname, s)
509
+ assert k not in self.buildfile_ids
510
+ self.buildfile_ids[k] = self.gen_id()
511
+ assert k not in self.fileref_ids
512
+ self.fileref_ids[k] = self.gen_id()
513
+ if not hasattr(t, 'objects'):
514
+ continue
515
+ for o in t.objects:
516
+ if isinstance(o, build.ExtractedObjects):
517
+ # Extracted objects do not live in "the Xcode world".
518
+ continue
519
+ if isinstance(o, mesonlib.File):
520
+ o = os.path.join(o.subdir, o.fname)
521
+ if isinstance(o, str):
522
+ o = os.path.join(t.subdir, o)
523
+ k = (tname, o)
524
+ assert k not in self.buildfile_ids
525
+ self.buildfile_ids[k] = self.gen_id()
526
+ assert k not in self.fileref_ids
527
+ self.fileref_ids[k] = self.gen_id()
528
+ else:
529
+ raise RuntimeError('Unknown input type ' + str(o))
530
+ for e in t.extra_files:
531
+ if isinstance(e, mesonlib.File):
532
+ e = os.path.join(e.subdir, e.fname)
533
+ if isinstance(e, str):
534
+ e = os.path.join(t.subdir, e)
535
+ k = (tname, e)
536
+ assert k not in self.buildfile_ids
537
+ self.buildfile_ids[k] = self.gen_id()
538
+ assert k not in self.fileref_ids
539
+ self.fileref_ids[k] = self.gen_id()
540
+
541
+ def generate_build_file_maps(self) -> None:
542
+ for buildfile in self.interpreter.get_build_def_files():
543
+ assert isinstance(buildfile, str)
544
+ self.buildfile_ids[buildfile] = self.gen_id()
545
+ self.fileref_ids[buildfile] = self.gen_id()
546
+
547
+ def generate_source_phase_map(self) -> None:
548
+ self.source_phase = {}
549
+ for t in self.build_targets:
550
+ self.source_phase[t] = self.gen_id()
551
+
552
+ def generate_pbx_aggregate_target(self, objects_dict: PbxDict) -> None:
553
+ self.custom_aggregate_targets = {}
554
+ self.build_all_tdep_id = self.gen_id()
555
+ target_dependencies = []
556
+ custom_target_dependencies = []
557
+ for tname, t in self.get_build_by_default_targets().items():
558
+ if isinstance(t, build.CustomTarget):
559
+ custom_target_dependencies.append(self.pbx_custom_dep_map[t.get_id()])
560
+ elif isinstance(t, build.BuildTarget):
561
+ target_dependencies.append(self.pbx_dep_map[t.get_id()])
562
+ aggregated_targets = []
563
+ aggregated_targets.append((self.all_id, 'ALL_BUILD',
564
+ self.all_buildconf_id,
565
+ [],
566
+ [self.regen_dependency_id] + target_dependencies + custom_target_dependencies))
567
+ aggregated_targets.append((self.test_id,
568
+ 'RUN_TESTS',
569
+ self.test_buildconf_id,
570
+ [self.test_command_id],
571
+ [self.regen_dependency_id, self.build_all_tdep_id]))
572
+ aggregated_targets.append((self.regen_id,
573
+ 'REGENERATE',
574
+ self.regen_buildconf_id,
575
+ [self.regen_command_id],
576
+ []))
577
+ for tname, t in self.build.get_custom_targets().items():
578
+ ct_id = self.gen_id()
579
+ self.custom_aggregate_targets[tname] = ct_id
580
+ build_phases = []
581
+ dependencies = [self.regen_dependency_id]
582
+ generator_id = 0
583
+ for d in t.dependencies:
584
+ if isinstance(d, build.CustomTarget):
585
+ dependencies.append(self.pbx_custom_dep_map[d.get_id()])
586
+ elif isinstance(d, build.BuildTarget):
587
+ dependencies.append(self.pbx_dep_map[d.get_id()])
588
+ for s in t.sources:
589
+ if isinstance(s, build.GeneratedList):
590
+ build_phases.append(self.shell_targets[(tname, generator_id)])
591
+ for d in s.depends:
592
+ dependencies.append(self.pbx_custom_dep_map[d.get_id()])
593
+ generator_id += 1
594
+ elif isinstance(s, build.ExtractedObjects):
595
+ source_target_id = self.pbx_dep_map[s.target.get_id()]
596
+ if source_target_id not in dependencies:
597
+ dependencies.append(source_target_id)
598
+ build_phases.append(self.shell_targets[tname])
599
+ aggregated_targets.append((ct_id, tname, self.buildconflistmap[tname], build_phases, dependencies))
600
+
601
+ # Sort objects by ID before writing
602
+ sorted_aggregated_targets = sorted(aggregated_targets, key=operator.itemgetter(0))
603
+ for t in sorted_aggregated_targets:
604
+ agt_dict = PbxDict()
605
+ name = t[1]
606
+ buildconf_id = t[2]
607
+ build_phases = t[3]
608
+ dependencies = t[4]
609
+ agt_dict.add_item('isa', 'PBXAggregateTarget')
610
+ agt_dict.add_item('buildConfigurationList', buildconf_id, f'Build configuration list for PBXAggregateTarget "{name}"')
611
+ bp_arr = PbxArray()
612
+ agt_dict.add_item('buildPhases', bp_arr)
613
+ for bp in build_phases:
614
+ bp_arr.add_item(bp, 'ShellScript')
615
+ dep_arr = PbxArray()
616
+ agt_dict.add_item('dependencies', dep_arr)
617
+ for td in dependencies:
618
+ dep_arr.add_item(td, 'PBXTargetDependency')
619
+ agt_dict.add_item('name', f'"{name}"')
620
+ agt_dict.add_item('productName', f'"{name}"')
621
+ objects_dict.add_item(t[0], agt_dict, name)
622
+
623
+ def generate_pbx_build_file(self, objects_dict: PbxDict) -> None:
624
+ for tname, t in self.build_targets.items():
625
+ for dep in t.get_external_deps():
626
+ if dep.name == 'appleframeworks':
627
+ for f in dep.frameworks:
628
+ fw_dict = PbxDict()
629
+ fwkey = self.native_frameworks[f]
630
+ if fwkey not in objects_dict.keys:
631
+ objects_dict.add_item(fwkey, fw_dict, f'{f}.framework in Frameworks')
632
+ fw_dict.add_item('isa', 'PBXBuildFile')
633
+ fw_dict.add_item('fileRef', self.native_frameworks_fileref[f], f)
634
+
635
+ for s in t.sources:
636
+ in_build_dir = False
637
+ if isinstance(s, mesonlib.File):
638
+ if s.is_built:
639
+ in_build_dir = True
640
+ s = os.path.join(s.subdir, s.fname)
641
+
642
+ if not isinstance(s, str):
643
+ continue
644
+ sdict = PbxDict()
645
+ k = (tname, s)
646
+ idval = self.buildfile_ids[k]
647
+ fileref = self.fileref_ids[k]
648
+ if in_build_dir:
649
+ fullpath = os.path.join(self.environment.get_build_dir(), s)
650
+ else:
651
+ fullpath = os.path.join(self.environment.get_source_dir(), s)
652
+ sdict.add_item('isa', 'PBXBuildFile')
653
+ sdict.add_item('fileRef', fileref, fullpath)
654
+ objects_dict.add_item(idval, sdict)
655
+
656
+ for o in t.objects:
657
+ if isinstance(o, build.ExtractedObjects):
658
+ # Object files are not source files as such. We add them
659
+ # by hand in linker flags. It is also not particularly
660
+ # clear how to define build files in Xcode's file format.
661
+ continue
662
+ if isinstance(o, mesonlib.File):
663
+ o = os.path.join(o.subdir, o.fname)
664
+ elif isinstance(o, str):
665
+ o = os.path.join(t.subdir, o)
666
+ idval = self.buildfile_ids[(tname, o)]
667
+ k = (tname, o)
668
+ fileref = self.fileref_ids[k]
669
+ assert o not in self.filemap
670
+ self.filemap[o] = idval
671
+ fullpath = os.path.join(self.environment.get_source_dir(), o)
672
+ fullpath2 = fullpath
673
+ o_dict = PbxDict()
674
+ objects_dict.add_item(idval, o_dict, fullpath)
675
+ o_dict.add_item('isa', 'PBXBuildFile')
676
+ o_dict.add_item('fileRef', fileref, fullpath2)
677
+
678
+ generator_id = 0
679
+ for g in t.generated:
680
+ if not isinstance(g, build.GeneratedList):
681
+ continue
682
+ self.create_generator_shellphase(objects_dict, tname, generator_id)
683
+ generator_id += 1
684
+
685
+ # Custom targets are shell build phases in Xcode terminology.
686
+ for tname, t in self.custom_targets.items():
687
+ if not isinstance(t, build.CustomTarget):
688
+ continue
689
+ (srcs, ofilenames, cmd) = self.eval_custom_target_command(t)
690
+ for o in ofilenames:
691
+ custom_dict = PbxDict()
692
+ objects_dict.add_item(self.custom_target_output_buildfile[o], custom_dict, f'/* {o} */')
693
+ custom_dict.add_item('isa', 'PBXBuildFile')
694
+ custom_dict.add_item('fileRef', self.custom_target_output_fileref[o])
695
+ generator_id = 0
696
+ for g in t.sources:
697
+ if not isinstance(g, build.GeneratedList):
698
+ continue
699
+ self.create_generator_shellphase(objects_dict, tname, generator_id)
700
+ generator_id += 1
701
+
702
+ def create_generator_shellphase(self, objects_dict, tname, generator_id) -> None:
703
+ file_ids = self.generator_buildfile_ids[(tname, generator_id)]
704
+ ref_ids = self.generator_fileref_ids[(tname, generator_id)]
705
+ assert len(ref_ids) == len(file_ids)
706
+ for file_o, ref_id in zip(file_ids, ref_ids):
707
+ odict = PbxDict()
708
+ objects_dict.add_item(file_o, odict)
709
+ odict.add_item('isa', 'PBXBuildFile')
710
+ odict.add_item('fileRef', ref_id)
711
+
712
+ def generate_pbx_build_style(self, objects_dict: PbxDict) -> None:
713
+ # FIXME: Xcode 9 and later does not uses PBXBuildStyle and it gets removed. Maybe we can remove this part.
714
+ for name, idval in self.buildstylemap.items():
715
+ styledict = PbxDict()
716
+ objects_dict.add_item(idval, styledict, name)
717
+ styledict.add_item('isa', 'PBXBuildStyle')
718
+ settings_dict = PbxDict()
719
+ styledict.add_item('buildSettings', settings_dict)
720
+ settings_dict.add_item('COPY_PHASE_STRIP', 'NO')
721
+ styledict.add_item('name', f'"{name}"')
722
+
723
+ def generate_pbx_container_item_proxy(self, objects_dict: PbxDict) -> None:
724
+ for t in self.build_targets:
725
+ proxy_dict = PbxDict()
726
+ objects_dict.add_item(self.containerproxy_map[t], proxy_dict, 'PBXContainerItemProxy')
727
+ proxy_dict.add_item('isa', 'PBXContainerItemProxy')
728
+ proxy_dict.add_item('containerPortal', self.project_uid, 'Project object')
729
+ proxy_dict.add_item('proxyType', '1')
730
+ proxy_dict.add_item('remoteGlobalIDString', self.native_targets[t])
731
+ proxy_dict.add_item('remoteInfo', '"' + t + '"')
732
+
733
+ def generate_pbx_file_reference(self, objects_dict: PbxDict) -> None:
734
+ for tname, t in self.build_targets.items():
735
+ for dep in t.get_external_deps():
736
+ if dep.name == 'appleframeworks':
737
+ for f in dep.frameworks:
738
+ fw_dict = PbxDict()
739
+ framework_fileref = self.native_frameworks_fileref[f]
740
+ if objects_dict.has_item(framework_fileref):
741
+ continue
742
+ objects_dict.add_item(framework_fileref, fw_dict, f)
743
+ fw_dict.add_item('isa', 'PBXFileReference')
744
+ fw_dict.add_item('lastKnownFileType', 'wrapper.framework')
745
+ fw_dict.add_item('name', f'{f}.framework')
746
+ fw_dict.add_item('path', f'System/Library/Frameworks/{f}.framework')
747
+ fw_dict.add_item('sourceTree', 'SDKROOT')
748
+ for s in t.sources:
749
+ in_build_dir = False
750
+ if isinstance(s, mesonlib.File):
751
+ if s.is_built:
752
+ in_build_dir = True
753
+ s = os.path.join(s.subdir, s.fname)
754
+ if not isinstance(s, str):
755
+ continue
756
+ idval = self.fileref_ids[(tname, s)]
757
+ fullpath = os.path.join(self.environment.get_source_dir(), s)
758
+ src_dict = PbxDict()
759
+ xcodetype = self.get_xcodetype(s)
760
+ name = os.path.basename(s)
761
+ path = s
762
+ objects_dict.add_item(idval, src_dict, fullpath)
763
+ src_dict.add_item('isa', 'PBXFileReference')
764
+ src_dict.add_item('explicitFileType', '"' + xcodetype + '"')
765
+ src_dict.add_item('fileEncoding', '4')
766
+ if in_build_dir:
767
+ src_dict.add_item('name', '"' + name + '"')
768
+ # This makes no sense. This should say path instead of name
769
+ # but then the path gets added twice.
770
+ src_dict.add_item('path', '"' + name + '"')
771
+ src_dict.add_item('sourceTree', 'BUILD_ROOT')
772
+ else:
773
+ src_dict.add_item('name', '"' + name + '"')
774
+ src_dict.add_item('path', '"' + path + '"')
775
+ src_dict.add_item('sourceTree', 'SOURCE_ROOT')
776
+
777
+ generator_id = 0
778
+ for g in t.generated:
779
+ if not isinstance(g, build.GeneratedList):
780
+ continue
781
+ outputs = self.generator_outputs[(tname, generator_id)]
782
+ ref_ids = self.generator_fileref_ids[tname, generator_id]
783
+ assert len(ref_ids) == len(outputs)
784
+ for o, ref_id in zip(outputs, ref_ids):
785
+ odict = PbxDict()
786
+ name = os.path.basename(o)
787
+ objects_dict.add_item(ref_id, odict, o)
788
+ xcodetype = self.get_xcodetype(o)
789
+ rel_name = mesonlib.relpath(o, self.environment.get_source_dir())
790
+ odict.add_item('isa', 'PBXFileReference')
791
+ odict.add_item('explicitFileType', '"' + xcodetype + '"')
792
+ odict.add_item('fileEncoding', '4')
793
+ odict.add_item('name', f'"{name}"')
794
+ odict.add_item('path', f'"{rel_name}"')
795
+ odict.add_item('sourceTree', 'SOURCE_ROOT')
796
+
797
+ generator_id += 1
798
+
799
+ for o in t.objects:
800
+ if isinstance(o, build.ExtractedObjects):
801
+ # Same as with pbxbuildfile.
802
+ continue
803
+ if isinstance(o, mesonlib.File):
804
+ fullpath = o.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())
805
+ o = os.path.join(o.subdir, o.fname)
806
+ else:
807
+ o = os.path.join(t.subdir, o)
808
+ fullpath = os.path.join(self.environment.get_source_dir(), o)
809
+ idval = self.fileref_ids[(tname, o)]
810
+ rel_name = mesonlib.relpath(fullpath, self.environment.get_source_dir())
811
+ o_dict = PbxDict()
812
+ name = os.path.basename(o)
813
+ objects_dict.add_item(idval, o_dict, fullpath)
814
+ o_dict.add_item('isa', 'PBXFileReference')
815
+ o_dict.add_item('explicitFileType', '"' + self.get_xcodetype(o) + '"')
816
+ o_dict.add_item('fileEncoding', '4')
817
+ o_dict.add_item('name', f'"{name}"')
818
+ o_dict.add_item('path', f'"{rel_name}"')
819
+ o_dict.add_item('sourceTree', 'SOURCE_ROOT')
820
+
821
+ for e in t.extra_files:
822
+ if isinstance(e, mesonlib.File):
823
+ e = os.path.join(e.subdir, e.fname)
824
+ else:
825
+ e = os.path.join(t.subdir, e)
826
+ idval = self.fileref_ids[(tname, e)]
827
+ fullpath = os.path.join(self.environment.get_source_dir(), e)
828
+ e_dict = PbxDict()
829
+ xcodetype = self.get_xcodetype(e)
830
+ name = os.path.basename(e)
831
+ path = e
832
+ objects_dict.add_item(idval, e_dict, fullpath)
833
+ e_dict.add_item('isa', 'PBXFileReference')
834
+ e_dict.add_item('explicitFileType', '"' + xcodetype + '"')
835
+ e_dict.add_item('name', '"' + name + '"')
836
+ e_dict.add_item('path', '"' + path + '"')
837
+ e_dict.add_item('sourceTree', 'SOURCE_ROOT')
838
+ for tname, idval in self.target_filemap.items():
839
+ target_dict = PbxDict()
840
+ objects_dict.add_item(idval, target_dict, tname)
841
+ t = self.build_targets[tname]
842
+ fname = t.get_filename()
843
+ reftype = 0
844
+ if isinstance(t, build.Executable):
845
+ typestr = 'compiled.mach-o.executable'
846
+ path = fname
847
+ elif isinstance(t, build.SharedLibrary):
848
+ typestr = self.get_xcodetype('dummy.dylib')
849
+ path = fname
850
+ else:
851
+ typestr = self.get_xcodetype(fname)
852
+ path = '"%s"' % t.get_filename()
853
+ target_dict.add_item('isa', 'PBXFileReference')
854
+ target_dict.add_item('explicitFileType', '"' + typestr + '"')
855
+ if ' ' in path and path[0] != '"':
856
+ target_dict.add_item('path', f'"{path}"')
857
+ else:
858
+ target_dict.add_item('path', path)
859
+ target_dict.add_item('refType', reftype)
860
+ target_dict.add_item('sourceTree', 'BUILT_PRODUCTS_DIR')
861
+
862
+ for tname, t in self.custom_targets.items():
863
+ if not isinstance(t, build.CustomTarget):
864
+ continue
865
+ (srcs, ofilenames, cmd) = self.eval_custom_target_command(t)
866
+ for s in t.sources:
867
+ if isinstance(s, mesonlib.File):
868
+ s = os.path.join(s.subdir, s.fname)
869
+ elif isinstance(s, str):
870
+ s = os.path.join(t.subdir, s)
871
+ else:
872
+ continue
873
+ custom_dict = PbxDict()
874
+ typestr = self.get_xcodetype(s)
875
+ custom_dict.add_item('isa', 'PBXFileReference')
876
+ custom_dict.add_item('explicitFileType', '"' + typestr + '"')
877
+ custom_dict.add_item('name', f'"{s}"')
878
+ custom_dict.add_item('path', f'"{s}"')
879
+ custom_dict.add_item('refType', 0)
880
+ custom_dict.add_item('sourceTree', 'SOURCE_ROOT')
881
+ objects_dict.add_item(self.fileref_ids[(tname, s)], custom_dict)
882
+ for o in ofilenames:
883
+ custom_dict = PbxDict()
884
+ typestr = self.get_xcodetype(o)
885
+ custom_dict.add_item('isa', 'PBXFileReference')
886
+ custom_dict.add_item('explicitFileType', '"' + typestr + '"')
887
+ custom_dict.add_item('name', o)
888
+ custom_dict.add_item('path', f'"{os.path.join(self.src_to_build, o)}"')
889
+ custom_dict.add_item('refType', 0)
890
+ custom_dict.add_item('sourceTree', 'SOURCE_ROOT')
891
+ objects_dict.add_item(self.custom_target_output_fileref[o], custom_dict)
892
+
893
+ for buildfile in self.interpreter.get_build_def_files():
894
+ basename = os.path.split(buildfile)[1]
895
+ buildfile_dict = PbxDict()
896
+ typestr = self.get_xcodetype(buildfile)
897
+ buildfile_dict.add_item('isa', 'PBXFileReference')
898
+ buildfile_dict.add_item('explicitFileType', '"' + typestr + '"')
899
+ buildfile_dict.add_item('name', f'"{basename}"')
900
+ buildfile_dict.add_item('path', f'"{buildfile}"')
901
+ buildfile_dict.add_item('refType', 0)
902
+ buildfile_dict.add_item('sourceTree', 'SOURCE_ROOT')
903
+ objects_dict.add_item(self.fileref_ids[buildfile], buildfile_dict)
904
+
905
+ def generate_pbx_frameworks_buildphase(self, objects_dict: PbxDict) -> None:
906
+ for t in self.build_targets.values():
907
+ bt_dict = PbxDict()
908
+ objects_dict.add_item(t.buildphasemap['Frameworks'], bt_dict, 'Frameworks')
909
+ bt_dict.add_item('isa', 'PBXFrameworksBuildPhase')
910
+ bt_dict.add_item('buildActionMask', 2147483647)
911
+ file_list = PbxArray()
912
+ bt_dict.add_item('files', file_list)
913
+ for dep in t.get_external_deps():
914
+ if dep.name == 'appleframeworks':
915
+ for f in dep.frameworks:
916
+ file_list.add_item(self.native_frameworks[f], f'{f}.framework in Frameworks')
917
+ bt_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
918
+
919
+ def generate_pbx_group(self, objects_dict: PbxDict) -> None:
920
+ groupmap = {}
921
+ target_src_map = {}
922
+ for t in self.build_targets:
923
+ groupmap[t] = self.gen_id()
924
+ target_src_map[t] = self.gen_id()
925
+ for t in self.custom_targets:
926
+ groupmap[t] = self.gen_id()
927
+ target_src_map[t] = self.gen_id()
928
+ projecttree_id = self.gen_id()
929
+ resources_id = self.gen_id()
930
+ products_id = self.gen_id()
931
+ frameworks_id = self.gen_id()
932
+ main_dict = PbxDict()
933
+ objects_dict.add_item(self.maingroup_id, main_dict)
934
+ main_dict.add_item('isa', 'PBXGroup')
935
+ main_children = PbxArray()
936
+ main_dict.add_item('children', main_children)
937
+ main_children.add_item(projecttree_id, 'Project tree')
938
+ main_children.add_item(resources_id, 'Resources')
939
+ main_children.add_item(products_id, 'Products')
940
+ main_children.add_item(frameworks_id, 'Frameworks')
941
+ main_dict.add_item('sourceTree', '"<group>"')
942
+
943
+ self.add_projecttree(objects_dict, projecttree_id)
944
+
945
+ resource_dict = PbxDict()
946
+ objects_dict.add_item(resources_id, resource_dict, 'Resources')
947
+ resource_dict.add_item('isa', 'PBXGroup')
948
+ resource_children = PbxArray()
949
+ resource_dict.add_item('children', resource_children)
950
+ resource_dict.add_item('name', 'Resources')
951
+ resource_dict.add_item('sourceTree', '"<group>"')
952
+
953
+ frameworks_dict = PbxDict()
954
+ objects_dict.add_item(frameworks_id, frameworks_dict, 'Frameworks')
955
+ frameworks_dict.add_item('isa', 'PBXGroup')
956
+ frameworks_children = PbxArray()
957
+ frameworks_dict.add_item('children', frameworks_children)
958
+ # write frameworks
959
+
960
+ for t in self.build_targets.values():
961
+ for dep in t.get_external_deps():
962
+ if dep.name == 'appleframeworks':
963
+ for f in dep.frameworks:
964
+ frameworks_children.add_item(self.native_frameworks_fileref[f], f)
965
+
966
+ frameworks_dict.add_item('name', 'Frameworks')
967
+ frameworks_dict.add_item('sourceTree', '"<group>"')
968
+
969
+ for tname, t in self.custom_targets.items():
970
+ target_dict = PbxDict()
971
+ objects_dict.add_item(groupmap[tname], target_dict, tname)
972
+ target_dict.add_item('isa', 'PBXGroup')
973
+ target_children = PbxArray()
974
+ target_dict.add_item('children', target_children)
975
+ target_children.add_item(target_src_map[tname], 'Source files')
976
+ if t.subproject:
977
+ target_dict.add_item('name', f'"{t.subproject} • {t.name}"')
978
+ else:
979
+ target_dict.add_item('name', f'"{t.name}"')
980
+ target_dict.add_item('sourceTree', '"<group>"')
981
+ source_files_dict = PbxDict()
982
+ objects_dict.add_item(target_src_map[tname], source_files_dict, 'Source files')
983
+ source_files_dict.add_item('isa', 'PBXGroup')
984
+ source_file_children = PbxArray()
985
+ source_files_dict.add_item('children', source_file_children)
986
+ for s in t.sources:
987
+ if isinstance(s, mesonlib.File):
988
+ s = os.path.join(s.subdir, s.fname)
989
+ elif isinstance(s, str):
990
+ s = os.path.join(t.subdir, s)
991
+ else:
992
+ continue
993
+ source_file_children.add_item(self.fileref_ids[(tname, s)], s)
994
+ source_files_dict.add_item('name', '"Source files"')
995
+ source_files_dict.add_item('sourceTree', '"<group>"')
996
+
997
+ # And finally products
998
+ product_dict = PbxDict()
999
+ objects_dict.add_item(products_id, product_dict, 'Products')
1000
+ product_dict.add_item('isa', 'PBXGroup')
1001
+ product_children = PbxArray()
1002
+ product_dict.add_item('children', product_children)
1003
+ for t in self.build_targets:
1004
+ product_children.add_item(self.target_filemap[t], t)
1005
+ product_dict.add_item('name', 'Products')
1006
+ product_dict.add_item('sourceTree', '"<group>"')
1007
+
1008
+ def write_group_target_entry(self, objects_dict, t):
1009
+ tid = t.get_id()
1010
+ group_id = self.gen_id()
1011
+ target_dict = PbxDict()
1012
+ objects_dict.add_item(group_id, target_dict, tid)
1013
+ target_dict.add_item('isa', 'PBXGroup')
1014
+ target_children = PbxArray()
1015
+ target_dict.add_item('children', target_children)
1016
+ target_dict.add_item('name', f'"{t} · target"')
1017
+ target_dict.add_item('sourceTree', '"<group>"')
1018
+ source_files_dict = PbxDict()
1019
+ for s in t.sources:
1020
+ if isinstance(s, mesonlib.File):
1021
+ s = os.path.join(s.subdir, s.fname)
1022
+ elif isinstance(s, str):
1023
+ s = os.path.join(t.subdir, s)
1024
+ else:
1025
+ continue
1026
+ target_children.add_item(self.fileref_ids[(tid, s)], s)
1027
+ for o in t.objects:
1028
+ if isinstance(o, build.ExtractedObjects):
1029
+ # Do not show built object files in the project tree.
1030
+ continue
1031
+ if isinstance(o, mesonlib.File):
1032
+ o = os.path.join(o.subdir, o.fname)
1033
+ else:
1034
+ o = os.path.join(t.subdir, o)
1035
+ target_children.add_item(self.fileref_ids[(tid, o)], o)
1036
+ for e in t.extra_files:
1037
+ if isinstance(e, mesonlib.File):
1038
+ e = os.path.join(e.subdir, e.fname)
1039
+ elif isinstance(e, str):
1040
+ e = os.path.join(t.subdir, e)
1041
+ else:
1042
+ continue
1043
+ target_children.add_item(self.fileref_ids[(tid, e)], e)
1044
+ source_files_dict.add_item('name', '"Source files"')
1045
+ source_files_dict.add_item('sourceTree', '"<group>"')
1046
+ return group_id
1047
+
1048
+ def add_projecttree(self, objects_dict, projecttree_id) -> None:
1049
+ root_dict = PbxDict()
1050
+ objects_dict.add_item(projecttree_id, root_dict, "Root of project tree")
1051
+ root_dict.add_item('isa', 'PBXGroup')
1052
+ target_children = PbxArray()
1053
+ root_dict.add_item('children', target_children)
1054
+ root_dict.add_item('name', '"Project root"')
1055
+ root_dict.add_item('sourceTree', '"<group>"')
1056
+
1057
+ project_tree = self.generate_project_tree()
1058
+ self.write_tree(objects_dict, project_tree, target_children, '')
1059
+
1060
+ def write_tree(self, objects_dict, tree_node, children_array, current_subdir) -> None:
1061
+ for subdir_name, subdir_node in tree_node.subdirs.items():
1062
+ subdir_dict = PbxDict()
1063
+ subdir_children = PbxArray()
1064
+ subdir_id = self.gen_id()
1065
+ objects_dict.add_item(subdir_id, subdir_dict)
1066
+ children_array.add_item(subdir_id)
1067
+ subdir_dict.add_item('isa', 'PBXGroup')
1068
+ subdir_dict.add_item('children', subdir_children)
1069
+ subdir_dict.add_item('name', f'"{subdir_name}"')
1070
+ subdir_dict.add_item('sourceTree', '"<group>"')
1071
+ self.write_tree(objects_dict, subdir_node, subdir_children, os.path.join(current_subdir, subdir_name))
1072
+ for target in tree_node.targets:
1073
+ group_id = self.write_group_target_entry(objects_dict, target)
1074
+ children_array.add_item(group_id)
1075
+ potentials = [os.path.join(current_subdir, 'meson.build'),
1076
+ os.path.join(current_subdir, 'meson.options'),
1077
+ os.path.join(current_subdir, 'meson_options.txt')]
1078
+ for bf in potentials:
1079
+ i = self.fileref_ids.get(bf, None)
1080
+ if i:
1081
+ children_array.add_item(i)
1082
+
1083
+ def generate_project_tree(self) -> FileTreeEntry:
1084
+ tree_info = FileTreeEntry()
1085
+ for tname, t in self.build_targets.items():
1086
+ self.add_target_to_tree(tree_info, t)
1087
+ return tree_info
1088
+
1089
+ def add_target_to_tree(self, tree_root: FileTreeEntry, t: build.BuildTarget) -> None:
1090
+ current_node = tree_root
1091
+ path_segments = t.subdir.split('/')
1092
+ for s in path_segments:
1093
+ if not s:
1094
+ continue
1095
+ if s not in current_node.subdirs:
1096
+ current_node.subdirs[s] = FileTreeEntry()
1097
+ current_node = current_node.subdirs[s]
1098
+ current_node.targets.append(t)
1099
+
1100
+ def generate_pbx_native_target(self, objects_dict: PbxDict) -> None:
1101
+ for tname, idval in self.native_targets.items():
1102
+ ntarget_dict = PbxDict()
1103
+ t = self.build_targets[tname]
1104
+ objects_dict.add_item(idval, ntarget_dict, tname)
1105
+ ntarget_dict.add_item('isa', 'PBXNativeTarget')
1106
+ ntarget_dict.add_item('buildConfigurationList', self.buildconflistmap[tname], f'Build configuration list for PBXNativeTarget "{tname}"')
1107
+ buildphases_array = PbxArray()
1108
+ ntarget_dict.add_item('buildPhases', buildphases_array)
1109
+ generator_id = 0
1110
+ for g in t.generated:
1111
+ # Custom target are handled via inter-target dependencies.
1112
+ # Generators are built as a shellscriptbuildphase.
1113
+ if isinstance(g, build.GeneratedList):
1114
+ buildphases_array.add_item(self.shell_targets[(tname, generator_id)], f'Generator {generator_id}/{tname}')
1115
+ generator_id += 1
1116
+ for bpname, bpval in t.buildphasemap.items():
1117
+ buildphases_array.add_item(bpval, f'{bpname} yyy')
1118
+ ntarget_dict.add_item('buildRules', PbxArray())
1119
+ dep_array = PbxArray()
1120
+ ntarget_dict.add_item('dependencies', dep_array)
1121
+ dep_array.add_item(self.regen_dependency_id)
1122
+ # These dependencies only tell Xcode that the deps must be built
1123
+ # before this one. They don't set up linkage or anything
1124
+ # like that. Those are set up in the XCBuildConfiguration.
1125
+ for lt in self.build_targets[tname].link_targets:
1126
+ # NOT DOCUMENTED, may need to make different links
1127
+ # to same target have different targetdependency item.
1128
+ if isinstance(lt, build.CustomTarget):
1129
+ dep_array.add_item(self.pbx_custom_dep_map[lt.get_id()], lt.name)
1130
+ elif isinstance(lt, build.CustomTargetIndex):
1131
+ dep_array.add_item(self.pbx_custom_dep_map[lt.target.get_id()], lt.target.name)
1132
+ else:
1133
+ idval = self.pbx_dep_map[lt.get_id()]
1134
+ dep_array.add_item(idval, 'PBXTargetDependency')
1135
+ for o in t.objects:
1136
+ if isinstance(o, build.ExtractedObjects):
1137
+ source_target_id = o.target.get_id()
1138
+ idval = self.pbx_dep_map[source_target_id]
1139
+ dep_array.add_item(idval, 'PBXTargetDependency')
1140
+ generator_id = 0
1141
+ for o in t.generated:
1142
+ if isinstance(o, build.CustomTarget):
1143
+ dep_array.add_item(self.pbx_custom_dep_map[o.get_id()], o.name)
1144
+ elif isinstance(o, build.CustomTargetIndex):
1145
+ dep_array.add_item(self.pbx_custom_dep_map[o.target.get_id()], o.target.name)
1146
+
1147
+ generator_id += 1
1148
+
1149
+ ntarget_dict.add_item('name', f'"{tname}"')
1150
+ ntarget_dict.add_item('productName', f'"{tname}"')
1151
+ ntarget_dict.add_item('productReference', self.target_filemap[tname], tname)
1152
+ if isinstance(t, build.Executable):
1153
+ typestr = 'com.apple.product-type.tool'
1154
+ elif isinstance(t, build.StaticLibrary):
1155
+ typestr = 'com.apple.product-type.library.static'
1156
+ elif isinstance(t, build.SharedLibrary):
1157
+ typestr = 'com.apple.product-type.library.dynamic'
1158
+ else:
1159
+ raise MesonException('Unknown target type for %s' % tname)
1160
+ ntarget_dict.add_item('productType', f'"{typestr}"')
1161
+
1162
+ def generate_pbx_project(self, objects_dict: PbxDict) -> None:
1163
+ project_dict = PbxDict()
1164
+ objects_dict.add_item(self.project_uid, project_dict, 'Project object')
1165
+ project_dict.add_item('isa', 'PBXProject')
1166
+ attr_dict = PbxDict()
1167
+ project_dict.add_item('attributes', attr_dict)
1168
+ attr_dict.add_item('BuildIndependentTargetsInParallel', 'YES')
1169
+ project_dict.add_item('buildConfigurationList', self.project_conflist, f'Build configuration list for PBXProject "{self.build.project_name}"')
1170
+ project_dict.add_item('buildSettings', PbxDict())
1171
+ style_arr = PbxArray()
1172
+ project_dict.add_item('buildStyles', style_arr)
1173
+ for name, idval in self.buildstylemap.items():
1174
+ style_arr.add_item(idval, name)
1175
+ project_dict.add_item('compatibilityVersion', '"Xcode 3.2"')
1176
+ project_dict.add_item('hasScannedForEncodings', 0)
1177
+ project_dict.add_item('mainGroup', self.maingroup_id)
1178
+ project_dict.add_item('projectDirPath', '"' + self.environment.get_source_dir() + '"')
1179
+ project_dict.add_item('projectRoot', '""')
1180
+ targets_arr = PbxArray()
1181
+ project_dict.add_item('targets', targets_arr)
1182
+ targets_arr.add_item(self.all_id, 'ALL_BUILD')
1183
+ targets_arr.add_item(self.test_id, 'RUN_TESTS')
1184
+ targets_arr.add_item(self.regen_id, 'REGENERATE')
1185
+ for t in self.build_targets:
1186
+ targets_arr.add_item(self.native_targets[t], t)
1187
+ for t in self.custom_targets:
1188
+ targets_arr.add_item(self.custom_aggregate_targets[t], t)
1189
+
1190
+ def generate_pbx_shell_build_phase(self, objects_dict: PbxDict) -> None:
1191
+ self.generate_test_shell_build_phase(objects_dict)
1192
+ self.generate_regen_shell_build_phase(objects_dict)
1193
+ self.generate_custom_target_shell_build_phases(objects_dict)
1194
+ self.generate_generator_target_shell_build_phases(objects_dict)
1195
+
1196
+ def generate_test_shell_build_phase(self, objects_dict: PbxDict) -> None:
1197
+ shell_dict = PbxDict()
1198
+ objects_dict.add_item(self.test_command_id, shell_dict, 'ShellScript')
1199
+ shell_dict.add_item('isa', 'PBXShellScriptBuildPhase')
1200
+ shell_dict.add_item('buildActionMask', 2147483647)
1201
+ shell_dict.add_item('files', PbxArray())
1202
+ shell_dict.add_item('inputPaths', PbxArray())
1203
+ shell_dict.add_item('outputPaths', PbxArray())
1204
+ shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
1205
+ shell_dict.add_item('shellPath', '/bin/sh')
1206
+ cmd = mesonlib.get_meson_command() + ['test', '--no-rebuild', '-C', self.environment.get_build_dir()]
1207
+ cmdstr = ' '.join(["'%s'" % i for i in cmd])
1208
+ shell_dict.add_item('shellScript', f'"{cmdstr}"')
1209
+ shell_dict.add_item('showEnvVarsInLog', 0)
1210
+
1211
+ def generate_regen_shell_build_phase(self, objects_dict: PbxDict) -> None:
1212
+ shell_dict = PbxDict()
1213
+ objects_dict.add_item(self.regen_command_id, shell_dict, 'ShellScript')
1214
+ shell_dict.add_item('isa', 'PBXShellScriptBuildPhase')
1215
+ shell_dict.add_item('buildActionMask', 2147483647)
1216
+ shell_dict.add_item('files', PbxArray())
1217
+ shell_dict.add_item('inputPaths', PbxArray())
1218
+ shell_dict.add_item('outputPaths', PbxArray())
1219
+ shell_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
1220
+ shell_dict.add_item('shellPath', '/bin/sh')
1221
+ cmd = mesonlib.get_meson_command() + ['--internal', 'regencheck', os.path.join(self.environment.get_build_dir(), 'meson-private')]
1222
+ cmdstr = ' '.join(["'%s'" % i for i in cmd])
1223
+ shell_dict.add_item('shellScript', f'"{cmdstr}"')
1224
+ shell_dict.add_item('showEnvVarsInLog', 0)
1225
+
1226
+ def generate_custom_target_shell_build_phases(self, objects_dict: PbxDict) -> None:
1227
+ # Custom targets are shell build phases in Xcode terminology.
1228
+ for tname, t in self.custom_targets.items():
1229
+ if not isinstance(t, build.CustomTarget):
1230
+ continue
1231
+ (srcs, ofilenames, cmd) = self.eval_custom_target_command(t, absolute_outputs=True)
1232
+ fixed_cmd, _ = self.as_meson_exe_cmdline(cmd[0],
1233
+ cmd[1:],
1234
+ capture=ofilenames[0] if t.capture else None,
1235
+ feed=srcs[0] if t.feed else None,
1236
+ env=t.env)
1237
+ custom_dict = PbxDict()
1238
+ objects_dict.add_item(self.shell_targets[tname], custom_dict, f'/* Custom target {tname} */')
1239
+ custom_dict.add_item('isa', 'PBXShellScriptBuildPhase')
1240
+ custom_dict.add_item('buildActionMask', 2147483647)
1241
+ custom_dict.add_item('files', PbxArray())
1242
+ custom_dict.add_item('inputPaths', PbxArray())
1243
+ outarray = PbxArray()
1244
+ custom_dict.add_item('name', '"Generate {}."'.format(ofilenames[0]))
1245
+ custom_dict.add_item('outputPaths', outarray)
1246
+ for o in ofilenames:
1247
+ outarray.add_item(f'"{os.path.join(self.environment.get_build_dir(), o)}"')
1248
+ custom_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
1249
+ custom_dict.add_item('shellPath', '/bin/sh')
1250
+ workdir = self.environment.get_build_dir()
1251
+ quoted_cmd = []
1252
+ for c in fixed_cmd:
1253
+ quoted_cmd.append(c.replace('"', chr(92) + '"'))
1254
+ cmdstr = ' '.join([f"\\'{x}\\'" for x in quoted_cmd])
1255
+ custom_dict.add_item('shellScript', f'"cd \'{workdir}\'; {cmdstr}"')
1256
+ custom_dict.add_item('showEnvVarsInLog', 0)
1257
+
1258
+ def generate_generator_target_shell_build_phases(self, objects_dict: PbxDict) -> None:
1259
+ for tname, t in self.build_targets.items():
1260
+ generator_id = 0
1261
+ for genlist in t.generated:
1262
+ if isinstance(genlist, build.GeneratedList):
1263
+ self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict)
1264
+ generator_id += 1
1265
+ for tname, t in self.custom_targets.items():
1266
+ generator_id = 0
1267
+ for genlist in t.sources:
1268
+ if isinstance(genlist, build.GeneratedList):
1269
+ self.generate_single_generator_phase(tname, t, genlist, generator_id, objects_dict)
1270
+ generator_id += 1
1271
+
1272
+ def generate_single_generator_phase(self, tname, t, genlist, generator_id, objects_dict) -> None:
1273
+ # TODO: this should be rewritten to use the meson wrapper, like the other generators do
1274
+ # Currently it doesn't handle a host binary that requires an exe wrapper correctly.
1275
+ generator = genlist.get_generator()
1276
+ exe = generator.get_exe()
1277
+ exe_arr = self.build_target_to_cmd_array(exe)
1278
+ workdir = self.environment.get_build_dir()
1279
+ target_private_dir = self.relpath(self.get_target_private_dir(t), self.get_target_dir(t))
1280
+ gen_dict = PbxDict()
1281
+ objects_dict.add_item(self.shell_targets[(tname, generator_id)], gen_dict, f'"Generator {generator_id}/{tname}"')
1282
+ infilelist = genlist.get_inputs()
1283
+ outfilelist = genlist.get_outputs()
1284
+ gen_dict.add_item('isa', 'PBXShellScriptBuildPhase')
1285
+ gen_dict.add_item('buildActionMask', 2147483647)
1286
+ gen_dict.add_item('files', PbxArray())
1287
+ gen_dict.add_item('inputPaths', PbxArray())
1288
+ gen_dict.add_item('name', f'"Generator {generator_id}/{tname}"')
1289
+ commands = [["cd", workdir]] # Array of arrays, each one a single command, will get concatenated below.
1290
+ k = (tname, generator_id)
1291
+ ofile_abs = self.generator_outputs[k]
1292
+ outarray = PbxArray()
1293
+ gen_dict.add_item('outputPaths', outarray)
1294
+ for of in ofile_abs:
1295
+ outarray.add_item(f'"{of}"')
1296
+ for i in infilelist:
1297
+ # This might be needed to be added to inputPaths. It's not done yet as it is
1298
+ # unclear whether it is necessary, what actually happens when it is defined
1299
+ # and currently the build works without it.
1300
+ #infile_abs = i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())
1301
+ infilename = i.rel_to_builddir(self.build_to_src, target_private_dir)
1302
+ base_args = generator.get_arglist(infilename)
1303
+ for o_base in genlist.get_outputs_for(i):
1304
+ o = os.path.join(self.get_target_private_dir(t), o_base)
1305
+ args = []
1306
+ for arg in base_args:
1307
+ arg = arg.replace("@INPUT@", infilename)
1308
+ arg = arg.replace('@OUTPUT@', o).replace('@BUILD_DIR@', self.get_target_private_dir(t))
1309
+ arg = arg.replace("@CURRENT_SOURCE_DIR@", os.path.join(self.build_to_src, t.subdir))
1310
+ args.append(arg)
1311
+ args = self.replace_outputs(args, self.get_target_private_dir(t), outfilelist)
1312
+ args = self.replace_extra_args(args, genlist)
1313
+ if generator.capture:
1314
+ # When capturing, stdout is the output. Forward it with the shell.
1315
+ full_command = ['('] + exe_arr + args + ['>', o, ')']
1316
+ else:
1317
+ full_command = exe_arr + args
1318
+ commands.append(full_command)
1319
+ gen_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
1320
+ gen_dict.add_item('shellPath', '/bin/sh')
1321
+ quoted_cmds = []
1322
+ for cmnd in commands:
1323
+ q = []
1324
+ for c in cmnd:
1325
+ if ' ' in c:
1326
+ q.append(f'\\"{c}\\"')
1327
+ else:
1328
+ q.append(c)
1329
+ quoted_cmds.append(' '.join(q))
1330
+ cmdstr = '"' + ' && '.join(quoted_cmds) + '"'
1331
+ gen_dict.add_item('shellScript', cmdstr)
1332
+ gen_dict.add_item('showEnvVarsInLog', 0)
1333
+
1334
+ def generate_pbx_sources_build_phase(self, objects_dict: PbxDict) -> None:
1335
+ for name in self.source_phase:
1336
+ phase_dict = PbxDict()
1337
+ t = self.build_targets[name]
1338
+ objects_dict.add_item(t.buildphasemap[name], phase_dict, 'Sources')
1339
+ phase_dict.add_item('isa', 'PBXSourcesBuildPhase')
1340
+ phase_dict.add_item('buildActionMask', 2147483647)
1341
+ file_arr = PbxArray()
1342
+ phase_dict.add_item('files', file_arr)
1343
+ for s in self.build_targets[name].sources:
1344
+ s = os.path.join(s.subdir, s.fname)
1345
+ if not self.environment.is_header(s):
1346
+ file_arr.add_item(self.buildfile_ids[(name, s)], os.path.join(self.environment.get_source_dir(), s))
1347
+ generator_id = 0
1348
+ for gt in t.generated:
1349
+ if isinstance(gt, build.CustomTarget):
1350
+ (srcs, ofilenames, cmd) = self.eval_custom_target_command(gt)
1351
+ for o in ofilenames:
1352
+ file_arr.add_item(self.custom_target_output_buildfile[o],
1353
+ os.path.join(self.environment.get_build_dir(), o))
1354
+ elif isinstance(gt, build.CustomTargetIndex):
1355
+ for o in gt.get_outputs():
1356
+ file_arr.add_item(self.custom_target_output_buildfile[o],
1357
+ os.path.join(self.environment.get_build_dir(), o))
1358
+ elif isinstance(gt, build.GeneratedList):
1359
+ genfiles = self.generator_buildfile_ids[(name, generator_id)]
1360
+ generator_id += 1
1361
+ for o in genfiles:
1362
+ file_arr.add_item(o)
1363
+ else:
1364
+ raise RuntimeError('Unknown input type: ' + str(gt))
1365
+ phase_dict.add_item('runOnlyForDeploymentPostprocessing', 0)
1366
+
1367
+ def generate_pbx_target_dependency(self, objects_dict: PbxDict) -> None:
1368
+ all_dict = PbxDict()
1369
+ objects_dict.add_item(self.build_all_tdep_id, all_dict, 'ALL_BUILD')
1370
+ all_dict.add_item('isa', 'PBXTargetDependency')
1371
+ all_dict.add_item('target', self.all_id)
1372
+ targets = []
1373
+ targets.append((self.regen_dependency_id, self.regen_id, 'REGEN', None))
1374
+ for t in self.build_targets:
1375
+ idval = self.pbx_dep_map[t] # VERIFY: is this correct?
1376
+ targets.append((idval, self.native_targets[t], t, self.containerproxy_map[t]))
1377
+
1378
+ for t in self.custom_targets:
1379
+ idval = self.pbx_custom_dep_map[t]
1380
+ targets.append((idval, self.custom_aggregate_targets[t], t, None)) # self.containerproxy_map[t]))
1381
+
1382
+ # Sort object by ID
1383
+ sorted_targets = sorted(targets, key=operator.itemgetter(0))
1384
+ for t in sorted_targets:
1385
+ t_dict = PbxDict()
1386
+ objects_dict.add_item(t[0], t_dict, 'PBXTargetDependency')
1387
+ t_dict.add_item('isa', 'PBXTargetDependency')
1388
+ t_dict.add_item('target', t[1], t[2])
1389
+ if t[3] is not None:
1390
+ t_dict.add_item('targetProxy', t[3], 'PBXContainerItemProxy')
1391
+
1392
+ def generate_xc_build_configuration(self, objects_dict: PbxDict) -> None:
1393
+ # First the setup for the toplevel project.
1394
+ for buildtype in self.buildtypes:
1395
+ bt_dict = PbxDict()
1396
+ objects_dict.add_item(self.project_configurations[buildtype], bt_dict, buildtype)
1397
+ bt_dict.add_item('isa', 'XCBuildConfiguration')
1398
+ settings_dict = PbxDict()
1399
+ bt_dict.add_item('buildSettings', settings_dict)
1400
+ settings_dict.add_item('ARCHS', f'"{self.arch}"')
1401
+ settings_dict.add_item('BUILD_DIR', f'"{self.environment.get_build_dir()}"')
1402
+ settings_dict.add_item('BUILD_ROOT', '"$(BUILD_DIR)"')
1403
+ settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES')
1404
+ settings_dict.add_item('SWIFT_VERSION', '5.0')
1405
+ settings_dict.add_item('SDKROOT', '"macosx"')
1406
+ settings_dict.add_item('OBJROOT', '"$(BUILD_DIR)/build"')
1407
+ bt_dict.add_item('name', f'"{buildtype}"')
1408
+
1409
+ # Then the all target.
1410
+ for buildtype in self.buildtypes:
1411
+ bt_dict = PbxDict()
1412
+ objects_dict.add_item(self.buildall_configurations[buildtype], bt_dict, buildtype)
1413
+ bt_dict.add_item('isa', 'XCBuildConfiguration')
1414
+ settings_dict = PbxDict()
1415
+ bt_dict.add_item('buildSettings', settings_dict)
1416
+ warn_array = PbxArray()
1417
+ warn_array.add_item('"$(inherited)"')
1418
+ settings_dict.add_item('WARNING_CFLAGS', warn_array)
1419
+
1420
+ bt_dict.add_item('name', f'"{buildtype}"')
1421
+
1422
+ # Then the test target.
1423
+ for buildtype in self.buildtypes:
1424
+ bt_dict = PbxDict()
1425
+ objects_dict.add_item(self.test_configurations[buildtype], bt_dict, buildtype)
1426
+ bt_dict.add_item('isa', 'XCBuildConfiguration')
1427
+ settings_dict = PbxDict()
1428
+ bt_dict.add_item('buildSettings', settings_dict)
1429
+ warn_array = PbxArray()
1430
+ settings_dict.add_item('WARNING_CFLAGS', warn_array)
1431
+ warn_array.add_item('"$(inherited)"')
1432
+ bt_dict.add_item('name', f'"{buildtype}"')
1433
+
1434
+ # Now finally targets.
1435
+ for target_name, target in self.build_targets.items():
1436
+ self.generate_single_build_target(objects_dict, target_name, target)
1437
+
1438
+ for target_name, target in self.custom_targets.items():
1439
+ bt_dict = PbxDict()
1440
+ objects_dict.add_item(self.buildconfmap[target_name][buildtype], bt_dict, buildtype)
1441
+ bt_dict.add_item('isa', 'XCBuildConfiguration')
1442
+ settings_dict = PbxDict()
1443
+ bt_dict.add_item('buildSettings', settings_dict)
1444
+ settings_dict.add_item('ARCHS', f'"{self.arch}"')
1445
+ settings_dict.add_item('ONLY_ACTIVE_ARCH', 'YES')
1446
+ settings_dict.add_item('SDKROOT', '"macosx"')
1447
+ bt_dict.add_item('name', f'"{buildtype}"')
1448
+
1449
+ def determine_internal_dep_link_args(self, target, buildtype):
1450
+ links_dylib = False
1451
+ dep_libs = []
1452
+ for l in target.link_targets:
1453
+ if isinstance(target, build.SharedModule) and isinstance(l, build.Executable):
1454
+ continue
1455
+ if isinstance(l, build.CustomTargetIndex):
1456
+ rel_dir = self.get_custom_target_output_dir(l.target)
1457
+ libname = l.get_filename()
1458
+ elif isinstance(l, build.CustomTarget):
1459
+ rel_dir = self.get_custom_target_output_dir(l)
1460
+ libname = l.get_filename()
1461
+ else:
1462
+ rel_dir = self.get_target_dir(l)
1463
+ libname = l.get_filename()
1464
+ abs_path = os.path.join(self.environment.get_build_dir(), rel_dir, libname)
1465
+ dep_libs.append("'%s'" % abs_path)
1466
+ if isinstance(l, build.SharedLibrary):
1467
+ links_dylib = True
1468
+ if isinstance(l, build.StaticLibrary):
1469
+ (sub_libs, sub_links_dylib) = self.determine_internal_dep_link_args(l, buildtype)
1470
+ dep_libs += sub_libs
1471
+ links_dylib = links_dylib or sub_links_dylib
1472
+ return (dep_libs, links_dylib)
1473
+
1474
+ def generate_single_build_target(self, objects_dict, target_name, target) -> None:
1475
+ for buildtype in self.buildtypes:
1476
+ dep_libs = []
1477
+ links_dylib = False
1478
+ headerdirs = []
1479
+ bridging_header = ""
1480
+ is_swift = self.is_swift_target(target)
1481
+ for d in target.get_include_dirs():
1482
+ for sd in d.expand_incdirs(self.environment.get_build_dir()):
1483
+ headerdirs.append(os.path.join(self.environment.get_source_dir(), sd.source))
1484
+ if sd.build is not None:
1485
+ headerdirs.append(os.path.join(self.environment.get_build_dir(), sd.build))
1486
+ for extra in d.expand_extra_build_dirs():
1487
+ headerdirs.append(os.path.join(self.environment.get_build_dir(), extra))
1488
+ # Swift can import declarations from C-based code using bridging headers.
1489
+ # There can only be one header, and it must be included as a source file.
1490
+ for i in target.get_sources():
1491
+ if self.environment.is_header(i) and is_swift:
1492
+ relh = i.rel_to_builddir(self.build_to_src)
1493
+ bridging_header = os.path.normpath(os.path.join(self.environment.get_build_dir(), relh))
1494
+ break
1495
+ (dep_libs, links_dylib) = self.determine_internal_dep_link_args(target, buildtype)
1496
+ if links_dylib:
1497
+ dep_libs = ['-Wl,-search_paths_first', '-Wl,-headerpad_max_install_names'] + dep_libs
1498
+ dylib_version = None
1499
+ if isinstance(target, build.SharedLibrary):
1500
+ if isinstance(target, build.SharedModule):
1501
+ ldargs = []
1502
+ else:
1503
+ ldargs = ['-dynamiclib']
1504
+ ldargs += ['-Wl,-headerpad_max_install_names'] + dep_libs
1505
+ install_path = os.path.join(self.environment.get_build_dir(), target.subdir, buildtype)
1506
+ dylib_version = target.soversion
1507
+ else:
1508
+ ldargs = dep_libs
1509
+ install_path = ''
1510
+ if dylib_version is not None:
1511
+ product_name = target.get_basename() + '.' + dylib_version
1512
+ else:
1513
+ product_name = target.get_basename()
1514
+ ldargs += target.link_args
1515
+ # Swift is special. Again. You can't mix Swift with other languages
1516
+ # in the same target. Thus for Swift we only use
1517
+ if is_swift:
1518
+ linker, stdlib_args = target.compilers['swift'], []
1519
+ else:
1520
+ linker, stdlib_args = self.determine_linker_and_stdlib_args(target)
1521
+ if not isinstance(target, build.StaticLibrary):
1522
+ ldargs += self.build.get_project_link_args(linker, target.subproject, target.for_machine)
1523
+ ldargs += self.build.get_global_link_args(linker, target.for_machine)
1524
+ cargs = []
1525
+ for dep in target.get_external_deps():
1526
+ cargs += dep.get_compile_args()
1527
+ ldargs += dep.get_link_args()
1528
+ for o in target.objects:
1529
+ # Add extracted objects to the link line by hand.
1530
+ if isinstance(o, build.ExtractedObjects):
1531
+ added_objs = set()
1532
+ for objname_rel in self.determine_ext_objs(o):
1533
+ objname_abs = os.path.join(self.environment.get_build_dir(), o.target.subdir, objname_rel)
1534
+ if objname_abs not in added_objs:
1535
+ added_objs.add(objname_abs)
1536
+ ldargs += [r'\"' + objname_abs + r'\"']
1537
+ generator_id = 0
1538
+ for o in target.generated:
1539
+ if isinstance(o, build.GeneratedList):
1540
+ outputs = self.generator_outputs[target_name, generator_id]
1541
+ generator_id += 1
1542
+ for o_abs in outputs:
1543
+ if o_abs.endswith('.o') or o_abs.endswith('.obj'):
1544
+ ldargs += [r'\"' + o_abs + r'\"']
1545
+ else:
1546
+ if isinstance(o, build.CustomTarget):
1547
+ (srcs, ofilenames, cmd) = self.eval_custom_target_command(o)
1548
+ for ofname in ofilenames:
1549
+ if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS:
1550
+ ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"']
1551
+ elif isinstance(o, build.CustomTargetIndex):
1552
+ for ofname in o.get_outputs():
1553
+ if os.path.splitext(ofname)[-1] in LINKABLE_EXTENSIONS:
1554
+ ldargs += [r'\"' + os.path.join(self.environment.get_build_dir(), ofname) + r'\"']
1555
+ else:
1556
+ raise RuntimeError(o)
1557
+ if isinstance(target, build.SharedModule):
1558
+ ldargs += linker.get_std_shared_module_link_args(target.get_options())
1559
+ elif isinstance(target, build.SharedLibrary):
1560
+ ldargs += linker.get_std_shared_lib_link_args()
1561
+ ldstr = ' '.join(ldargs)
1562
+ valid = self.buildconfmap[target_name][buildtype]
1563
+ langargs = {}
1564
+ for lang in self.environment.coredata.compilers[target.for_machine]:
1565
+ if lang not in LANGNAMEMAP:
1566
+ continue
1567
+ compiler = target.compilers.get(lang)
1568
+ if compiler is None:
1569
+ continue
1570
+ # Start with warning args
1571
+ warn_args = compiler.get_warn_args(target.get_option(OptionKey('warning_level')))
1572
+ copt_proxy = target.get_options()
1573
+ std_args = compiler.get_option_compile_args(copt_proxy)
1574
+ # Add compile args added using add_project_arguments()
1575
+ pargs = self.build.projects_args[target.for_machine].get(target.subproject, {}).get(lang, [])
1576
+ # Add compile args added using add_global_arguments()
1577
+ # These override per-project arguments
1578
+ gargs = self.build.global_args[target.for_machine].get(lang, [])
1579
+ targs = target.get_extra_args(lang)
1580
+ args = warn_args + std_args + pargs + gargs + targs
1581
+ if lang == 'swift':
1582
+ # For some reason putting Swift module dirs in HEADER_SEARCH_PATHS does not work,
1583
+ # but adding -I/path to manual args does work.
1584
+ swift_dep_dirs = self.determine_swift_dep_dirs(target)
1585
+ for d in swift_dep_dirs:
1586
+ args += compiler.get_include_args(d, False)
1587
+ if args:
1588
+ lang_cargs = cargs
1589
+ if compiler and target.implicit_include_directories:
1590
+ # It is unclear what is the cwd when xcode runs. -I. does not seem to
1591
+ # add the root build dir to the search path. So add an absolute path instead.
1592
+ # This may break reproducible builds, in which case patches are welcome.
1593
+ lang_cargs += self.get_custom_target_dir_include_args(target, compiler, absolute_path=True)
1594
+ # Xcode cannot handle separate compilation flags for C and ObjectiveC. They are both
1595
+ # put in OTHER_CFLAGS. Same with C++ and ObjectiveC++.
1596
+ if lang == 'objc':
1597
+ lang = 'c'
1598
+ elif lang == 'objcpp':
1599
+ lang = 'cpp'
1600
+ langname = LANGNAMEMAP[lang]
1601
+ if langname in langargs:
1602
+ langargs[langname] += args
1603
+ else:
1604
+ langargs[langname] = args
1605
+ langargs[langname] += lang_cargs
1606
+ symroot = os.path.join(self.environment.get_build_dir(), target.subdir)
1607
+ bt_dict = PbxDict()
1608
+ objects_dict.add_item(valid, bt_dict, buildtype)
1609
+ bt_dict.add_item('isa', 'XCBuildConfiguration')
1610
+ settings_dict = PbxDict()
1611
+ bt_dict.add_item('buildSettings', settings_dict)
1612
+ settings_dict.add_item('COMBINE_HIDPI_IMAGES', 'YES')
1613
+ if isinstance(target, build.SharedModule):
1614
+ settings_dict.add_item('DYLIB_CURRENT_VERSION', '""')
1615
+ settings_dict.add_item('DYLIB_COMPATIBILITY_VERSION', '""')
1616
+ else:
1617
+ if dylib_version is not None:
1618
+ settings_dict.add_item('DYLIB_CURRENT_VERSION', f'"{dylib_version}"')
1619
+ if target.prefix:
1620
+ settings_dict.add_item('EXECUTABLE_PREFIX', target.prefix)
1621
+ if target.suffix:
1622
+ suffix = '.' + target.suffix
1623
+ settings_dict.add_item('EXECUTABLE_SUFFIX', suffix)
1624
+ settings_dict.add_item('GCC_GENERATE_DEBUGGING_SYMBOLS', BOOL2XCODEBOOL[target.get_option(OptionKey('debug'))])
1625
+ settings_dict.add_item('GCC_INLINES_ARE_PRIVATE_EXTERN', 'NO')
1626
+ opt_flag = OPT2XCODEOPT[target.get_option(OptionKey('optimization'))]
1627
+ if opt_flag is not None:
1628
+ settings_dict.add_item('GCC_OPTIMIZATION_LEVEL', opt_flag)
1629
+ if target.has_pch:
1630
+ # Xcode uses GCC_PREFIX_HEADER which only allows one file per target/executable. Precompiling various header files and
1631
+ # applying a particular pch to each source file will require custom scripts (as a build phase) and build flags per each
1632
+ # file. Since Xcode itself already discourages precompiled headers in favor of modules we don't try much harder here.
1633
+ pchs = target.get_pch('c') + target.get_pch('cpp') + target.get_pch('objc') + target.get_pch('objcpp')
1634
+ # Make sure to use headers (other backends require implementation files like *.c *.cpp, etc; these should not be used here)
1635
+ pchs = [pch for pch in pchs if pch.endswith('.h') or pch.endswith('.hh') or pch.endswith('hpp')]
1636
+ if pchs:
1637
+ if len(pchs) > 1:
1638
+ mlog.warning(f'Unsupported Xcode configuration: More than 1 precompiled header found "{pchs!s}". Target "{target.name}" might not compile correctly.')
1639
+ relative_pch_path = os.path.join(target.get_source_subdir(), pchs[0]) # Path relative to target so it can be used with "$(PROJECT_DIR)"
1640
+ settings_dict.add_item('GCC_PRECOMPILE_PREFIX_HEADER', 'YES')
1641
+ settings_dict.add_item('GCC_PREFIX_HEADER', f'"$(PROJECT_DIR)/{relative_pch_path}"')
1642
+ settings_dict.add_item('GCC_PREPROCESSOR_DEFINITIONS', '""')
1643
+ settings_dict.add_item('GCC_SYMBOLS_PRIVATE_EXTERN', 'NO')
1644
+ header_arr = PbxArray()
1645
+ unquoted_headers = []
1646
+ unquoted_headers.append(self.get_target_private_dir_abs(target))
1647
+ if target.implicit_include_directories:
1648
+ unquoted_headers.append(os.path.join(self.environment.get_build_dir(), target.get_output_subdir()))
1649
+ unquoted_headers.append(os.path.join(self.environment.get_source_dir(), target.get_source_subdir()))
1650
+ if headerdirs:
1651
+ for i in headerdirs:
1652
+ i = os.path.normpath(i)
1653
+ unquoted_headers.append(i)
1654
+ for i in unquoted_headers:
1655
+ header_arr.add_item(f'"\\"{i}\\""')
1656
+ settings_dict.add_item('HEADER_SEARCH_PATHS', header_arr)
1657
+ settings_dict.add_item('INSTALL_PATH', f'"{install_path}"')
1658
+ settings_dict.add_item('LIBRARY_SEARCH_PATHS', '""')
1659
+ if isinstance(target, build.SharedModule):
1660
+ settings_dict.add_item('LIBRARY_STYLE', 'BUNDLE')
1661
+ settings_dict.add_item('MACH_O_TYPE', 'mh_bundle')
1662
+ elif isinstance(target, build.SharedLibrary):
1663
+ settings_dict.add_item('LIBRARY_STYLE', 'DYNAMIC')
1664
+ self.add_otherargs(settings_dict, langargs)
1665
+ settings_dict.add_item('OTHER_LDFLAGS', f'"{ldstr}"')
1666
+ settings_dict.add_item('OTHER_REZFLAGS', '""')
1667
+ if ' ' in product_name:
1668
+ settings_dict.add_item('PRODUCT_NAME', f'"{product_name}"')
1669
+ else:
1670
+ settings_dict.add_item('PRODUCT_NAME', product_name)
1671
+ settings_dict.add_item('SECTORDER_FLAGS', '""')
1672
+ if is_swift and bridging_header:
1673
+ settings_dict.add_item('SWIFT_OBJC_BRIDGING_HEADER', f'"{bridging_header}"')
1674
+ settings_dict.add_item('BUILD_DIR', f'"{symroot}"')
1675
+ settings_dict.add_item('OBJROOT', f'"{symroot}/build"')
1676
+ sysheader_arr = PbxArray()
1677
+ # XCode will change every -I flag that points inside these directories
1678
+ # to an -isystem. Thus set nothing in it since we control our own
1679
+ # include flags.
1680
+ settings_dict.add_item('SYSTEM_HEADER_SEARCH_PATHS', sysheader_arr)
1681
+ settings_dict.add_item('USE_HEADERMAP', 'NO')
1682
+ warn_array = PbxArray()
1683
+ settings_dict.add_item('WARNING_CFLAGS', warn_array)
1684
+ warn_array.add_item('"$(inherited)"')
1685
+ bt_dict.add_item('name', buildtype)
1686
+
1687
+ def add_otherargs(self, settings_dict, langargs):
1688
+ for langname, args in langargs.items():
1689
+ if args:
1690
+ quoted_args = []
1691
+ for a in args:
1692
+ # This works but
1693
+ # a) it's ugly as sin
1694
+ # b) I don't know why it works or why every backslash must be escaped into eight backslashes
1695
+ a = a.replace(chr(92), 8*chr(92)) # chr(92) is backslash, this how we smuggle it in without Python's quoting grabbing it.
1696
+ a = a.replace(r'"', r'\\\"')
1697
+ if ' ' in a or "'" in a:
1698
+ a = r'\"' + a + r'\"'
1699
+ quoted_args.append(a)
1700
+ settings_dict.add_item(f'OTHER_{langname}FLAGS', '"' + ' '.join(quoted_args) + '"')
1701
+
1702
+ def generate_xc_configurationList(self, objects_dict: PbxDict) -> None:
1703
+ # FIXME: sort items
1704
+ conf_dict = PbxDict()
1705
+ objects_dict.add_item(self.project_conflist, conf_dict, f'Build configuration list for PBXProject "{self.build.project_name}"')
1706
+ conf_dict.add_item('isa', 'XCConfigurationList')
1707
+ confs_arr = PbxArray()
1708
+ conf_dict.add_item('buildConfigurations', confs_arr)
1709
+ for buildtype in self.buildtypes:
1710
+ confs_arr.add_item(self.project_configurations[buildtype], buildtype)
1711
+ conf_dict.add_item('defaultConfigurationIsVisible', 0)
1712
+ conf_dict.add_item('defaultConfigurationName', self.buildtype)
1713
+
1714
+ # Now the all target
1715
+ all_dict = PbxDict()
1716
+ objects_dict.add_item(self.all_buildconf_id, all_dict, 'Build configuration list for PBXAggregateTarget "ALL_BUILD"')
1717
+ all_dict.add_item('isa', 'XCConfigurationList')
1718
+ conf_arr = PbxArray()
1719
+ all_dict.add_item('buildConfigurations', conf_arr)
1720
+ for buildtype in self.buildtypes:
1721
+ conf_arr.add_item(self.buildall_configurations[buildtype], buildtype)
1722
+ all_dict.add_item('defaultConfigurationIsVisible', 0)
1723
+ all_dict.add_item('defaultConfigurationName', self.buildtype)
1724
+
1725
+ # Test target
1726
+ test_dict = PbxDict()
1727
+ objects_dict.add_item(self.test_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "RUN_TEST"')
1728
+ test_dict.add_item('isa', 'XCConfigurationList')
1729
+ conf_arr = PbxArray()
1730
+ test_dict.add_item('buildConfigurations', conf_arr)
1731
+ for buildtype in self.buildtypes:
1732
+ conf_arr.add_item(self.test_configurations[buildtype], buildtype)
1733
+ test_dict.add_item('defaultConfigurationIsVisible', 0)
1734
+ test_dict.add_item('defaultConfigurationName', self.buildtype)
1735
+
1736
+ # Regen target
1737
+ regen_dict = PbxDict()
1738
+ objects_dict.add_item(self.regen_buildconf_id, test_dict, 'Build configuration list for PBXAggregateTarget "REGENERATE"')
1739
+ regen_dict.add_item('isa', 'XCConfigurationList')
1740
+ conf_arr = PbxArray()
1741
+ regen_dict.add_item('buildConfigurations', conf_arr)
1742
+ for buildtype in self.buildtypes:
1743
+ conf_arr.add_item(self.test_configurations[buildtype], buildtype)
1744
+ regen_dict.add_item('defaultConfigurationIsVisible', 0)
1745
+ regen_dict.add_item('defaultConfigurationName', self.buildtype)
1746
+
1747
+ for target_name in self.build_targets:
1748
+ t_dict = PbxDict()
1749
+ listid = self.buildconflistmap[target_name]
1750
+ objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXNativeTarget "{target_name}"')
1751
+ t_dict.add_item('isa', 'XCConfigurationList')
1752
+ conf_arr = PbxArray()
1753
+ t_dict.add_item('buildConfigurations', conf_arr)
1754
+ idval = self.buildconfmap[target_name][self.buildtype]
1755
+ conf_arr.add_item(idval, self.buildtype)
1756
+ t_dict.add_item('defaultConfigurationIsVisible', 0)
1757
+ t_dict.add_item('defaultConfigurationName', self.buildtype)
1758
+
1759
+ for target_name in self.custom_targets:
1760
+ t_dict = PbxDict()
1761
+ listid = self.buildconflistmap[target_name]
1762
+ objects_dict.add_item(listid, t_dict, f'Build configuration list for PBXAggregateTarget "{target_name}"')
1763
+ t_dict.add_item('isa', 'XCConfigurationList')
1764
+ conf_arr = PbxArray()
1765
+ t_dict.add_item('buildConfigurations', conf_arr)
1766
+ idval = self.buildconfmap[target_name][self.buildtype]
1767
+ conf_arr.add_item(idval, self.buildtype)
1768
+ t_dict.add_item('defaultConfigurationIsVisible', 0)
1769
+ t_dict.add_item('defaultConfigurationName', self.buildtype)
1770
+
1771
+ def generate_prefix(self, pbxdict: PbxDict) -> PbxDict:
1772
+ pbxdict.add_item('archiveVersion', '1')
1773
+ pbxdict.add_item('classes', PbxDict())
1774
+ pbxdict.add_item('objectVersion', '46')
1775
+ objects_dict = PbxDict()
1776
+ pbxdict.add_item('objects', objects_dict)
1777
+
1778
+ return objects_dict
1779
+
1780
+ def generate_suffix(self, pbxdict: PbxDict) -> None:
1781
+ pbxdict.add_item('rootObject', self.project_uid, 'Project object')