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